Don't assert on broken DM names.
[mono.git] / mono / metadata / reflection.c
index 4b68dec62d640b6d59750d13bfca8f9e753b1538..bd03a87baa03a4e48c0a3b66ebaad6c5d9936617 100644 (file)
 #include <mono/metadata/gc-internal.h>
 #include <mono/metadata/mempool-internals.h>
 #include <mono/metadata/security-core-clr.h>
+#include <mono/metadata/debug-helpers.h>
+#include <mono/metadata/verify-internals.h>
+#include <mono/metadata/mono-ptr-array.h>
+#include <mono/utils/mono-string.h>
+#include <mono/utils/mono-error-internals.h>
 
-#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 ((char*)(addr), sizeof (gpointer), reflection_info_desc); \
-       } while (0)
-#else
-#define MOVING_GC_REGISTER(addr)
-#endif
+static gboolean is_usertype (MonoReflectionType *ref);
+static MonoReflectionType *mono_reflection_type_resolve_user_types (MonoReflectionType *type);
 
 typedef struct {
        char *p;
@@ -150,7 +145,7 @@ const unsigned char table_sizes [MONO_TABLE_NUM] = {
 
 #ifndef DISABLE_REFLECTION_EMIT
 static guint32 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method, gboolean create_typespec);
-static guint32 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, gboolean create_methodspec);
+static guint32 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, gboolean create_open_instance);
 static guint32 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *cb);
 static guint32 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper);
 static void    ensure_runtime_vtable (MonoClass *klass);
@@ -158,10 +153,11 @@ static gpointer resolve_object (MonoImage *image, MonoObject *obj, MonoClass **h
 static guint32 mono_image_get_methodref_token_for_methodbuilder (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *method);
 static guint32 encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericContext *context);
 static gpointer register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly);
-#endif
-
 static void reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb);
 static void reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb);
+static guint32 create_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb);
+#endif
+
 static guint32 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type);
 static guint32 mono_image_typedef_or_ref_full (MonoDynamicImage *assembly, MonoType *type, gboolean try_typespec);
 static void    mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly);
@@ -170,9 +166,40 @@ static guint32 encode_constant (MonoDynamicImage *assembly, MonoObject *val, gui
 static char*   type_get_qualified_name (MonoType *type, MonoAssembly *ass);
 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);
+static MonoReflectionType* mono_reflection_type_resolve_user_types (MonoReflectionType *type);
+static gboolean is_sre_array (MonoClass *class);
+static gboolean is_sre_byref (MonoClass *class);
+static gboolean is_sre_pointer (MonoClass *class);
+static gboolean is_sre_type_builder (MonoClass *class);
+static gboolean is_sre_method_builder (MonoClass *class);
+static gboolean is_sre_ctor_builder (MonoClass *class);
+static gboolean is_sre_field_builder (MonoClass *class);
+static gboolean is_sr_mono_method (MonoClass *class);
+static gboolean is_sr_mono_cmethod (MonoClass *class);
+static gboolean is_sr_mono_generic_method (MonoClass *class);
+static gboolean is_sr_mono_generic_cmethod (MonoClass *class);
+static gboolean is_sr_mono_field (MonoClass *class);
+static gboolean is_sr_mono_property (MonoClass *class);
+static gboolean is_sre_method_on_tb_inst (MonoClass *class);
+static gboolean is_sre_ctor_on_tb_inst (MonoClass *class);
+
+static guint32 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *method);
+static guint32 mono_image_get_inflated_method_token (MonoDynamicImage *assembly, MonoMethod *m);
+static MonoMethod * inflate_method (MonoReflectionType *type, MonoObject *obj);
+
+static guint32 create_typespec (MonoDynamicImage *assembly, MonoType *type);
+static void init_type_builder_generics (MonoObject *type);
+
+#define RESOLVE_TYPE(type) do { type = (void*)mono_reflection_type_resolve_user_types ((MonoReflectionType*)type); } while (0)
+#define RESOLVE_ARRAY_TYPE_ELEMENT(array, index) do {  \
+       MonoReflectionType *__type = mono_array_get (array, MonoReflectionType*, index);        \
+       __type = mono_reflection_type_resolve_user_types (__type);      \
+       mono_array_set (arr, MonoReflectionType*, index, __type);       \
+} while (0)
+
+#define mono_type_array_get_and_resolve(array, index) mono_reflection_type_get_handle ((MonoReflectionType*)mono_array_get (array, gpointer, index))
 
 void
 mono_reflection_init (void)
@@ -579,6 +606,36 @@ default_class_from_mono_type (MonoType *type)
 }
 #endif
 
+/*
+ * mono_class_get_ref_info:
+ *
+ *   Return the type builder/generic param builder corresponding to KLASS, if it exists.
+ */
+gpointer
+mono_class_get_ref_info (MonoClass *klass)
+{
+       if (klass->ref_info_handle == 0)
+               return NULL;
+       else
+               return mono_gchandle_get_target (klass->ref_info_handle);
+}
+
+void
+mono_class_set_ref_info (MonoClass *klass, gpointer obj)
+{
+       klass->ref_info_handle = mono_gchandle_new ((MonoObject*)obj, FALSE);
+       g_assert (klass->ref_info_handle != 0);
+}
+
+void
+mono_class_free_ref_info (MonoClass *klass)
+{
+       if (klass->ref_info_handle) {
+               mono_gchandle_free (klass->ref_info_handle);
+               klass->ref_info_handle = 0;
+       }
+}
+
 static void
 encode_generic_class (MonoDynamicImage *assembly, MonoGenericClass *gclass, SigBuffer *buf)
 {
@@ -690,14 +747,7 @@ encode_reflection_type (MonoDynamicImage *assembly, MonoReflectionType *type, Si
                return;
        }
 
-       if (type->type ||
-            ((type = mono_reflection_type_get_underlying_system_type (type)) && type->type)) {
-               encode_type (assembly, type->type, buf);
-               return;
-       }
-
-       g_assert_not_reached ();
-
+       encode_type (assembly, mono_reflection_type_get_handle (type), buf);
 }
 
 static void
@@ -707,16 +757,16 @@ encode_custom_modifiers (MonoDynamicImage *assembly, MonoArray *modreq, MonoArra
 
        if (modreq) {
                for (i = 0; i < mono_array_length (modreq); ++i) {
-                       MonoReflectionType *mod = mono_type_array_get (modreq, i);
+                       MonoType *mod = mono_type_array_get_and_resolve (modreq, i);
                        sigbuffer_add_byte (buf, MONO_TYPE_CMOD_REQD);
-                       sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, mod->type));
+                       sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, mod));
                }
        }
        if (modopt) {
                for (i = 0; i < mono_array_length (modopt); ++i) {
-                       MonoReflectionType *mod = mono_type_array_get (modopt, i);
+                       MonoType *mod = mono_type_array_get_and_resolve (modopt, i);
                        sigbuffer_add_byte (buf, MONO_TYPE_CMOD_OPT);
-                       sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, mod->type));
+                       sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, mod));
                }
        }
 }
@@ -796,7 +846,7 @@ method_builder_encode_signature (MonoDynamicImage *assembly, ReflectionMethodBui
                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, &buf);
-               pt = mono_type_array_get (mb->parameters, i);
+               pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
                encode_reflection_type (assembly, pt, &buf);
        }
        if (notypes)
@@ -804,7 +854,7 @@ method_builder_encode_signature (MonoDynamicImage *assembly, ReflectionMethodBui
        for (i = 0; i < notypes; ++i) {
                MonoReflectionType *pt;
 
-               pt = mono_type_array_get (mb->opt_types, i);
+               pt = mono_array_get (mb->opt_types, MonoReflectionType*, i);
                encode_reflection_type (assembly, pt, &buf);
        }
 
@@ -832,7 +882,7 @@ encode_locals (MonoDynamicImage *assembly, MonoReflectionILGen *ilgen)
                if (lb->is_pinned)
                        sigbuffer_add_value (&buf, MONO_TYPE_PINNED);
                
-               encode_reflection_type (assembly, monotype_cast (lb->type), &buf);
+               encode_reflection_type (assembly, (MonoReflectionType*)lb->type, &buf);
        }
        sig_idx = sigbuffer_add_to_blob_cached (assembly, &buf);
        sigbuffer_free (&buf);
@@ -907,7 +957,7 @@ method_encode_clauses (MonoImage *image, MonoDynamicImage *assembly, MonoReflect
                        clause->handler_offset = ex_block->start;
                        clause->handler_len = ex_block->len;
                        if (ex_block->extype) {
-                               clause->data.catch_class = mono_class_from_mono_type (monotype_cast (ex_block->extype)->type);
+                               clause->data.catch_class = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)ex_block->extype));
                        } else {
                                if (ex_block->type == MONO_EXCEPTION_CLAUSE_FILTER)
                                        clause->data.filter_offset = ex_block->filter_offset;
@@ -1059,7 +1109,7 @@ fat_header:
                                        mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
                                        finally_start = ex_block->start + ex_block->len;
                                        if (ex_block->extype) {
-                                               val = mono_metadata_token_from_dor (mono_image_typedef_or_ref (assembly, monotype_cast (ex_block->extype)->type));
+                                               val = mono_metadata_token_from_dor (mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)ex_block->extype)));
                                        } else {
                                                if (ex_block->type == MONO_EXCEPTION_CLAUSE_FILTER)
                                                        val = ex_block->filter_offset;
@@ -1112,7 +1162,9 @@ lookup_custom_attr (MonoImage *image, gpointer member)
        if (!res)
                return NULL;
 
-       return g_memdup (res, sizeof (MonoCustomAttrInfo) + sizeof (MonoCustomAttrEntry) * (res->num_attrs - MONO_ZERO_LEN_ARRAY));
+       res = g_memdup (res, MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * res->num_attrs);
+       res->cached = 0;
+       return res;
 }
 
 static gboolean
@@ -1152,7 +1204,7 @@ mono_custom_attrs_from_builders (MonoImage *alloc_img, MonoImage *image, MonoArr
        }
        count -= not_visible;
 
-       ainfo = image_g_malloc0 (alloc_img, sizeof (MonoCustomAttrInfo) + sizeof (MonoCustomAttrEntry) * (count - MONO_ZERO_LEN_ARRAY));
+       ainfo = image_g_malloc0 (alloc_img, MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * count);
 
        ainfo->image = image;
        ainfo->num_attrs = count;
@@ -1378,13 +1430,14 @@ mono_image_basic_method (ReflectionMethodBuilder *mb, MonoDynamicImage *assembly
        }
 }
 
+#ifndef DISABLE_REFLECTION_EMIT
 static void
 reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb)
 {
        memset (rmb, 0, sizeof (ReflectionMethodBuilder));
 
        rmb->ilgen = mb->ilgen;
-       rmb->rtype = monotype_cast (mb->rtype);
+       rmb->rtype = mono_reflection_type_resolve_user_types ((MonoReflectionType*)mb->rtype);
        rmb->parameters = mb->parameters;
        rmb->generic_params = mb->generic_params;
        rmb->generic_container = mb->generic_container;
@@ -1450,7 +1503,6 @@ reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoRe
        rmb->refs = NULL;
 }
 
-#ifndef DISABLE_REFLECTION_EMIT
 static void
 reflection_methodbuilder_from_dynamic_method (ReflectionMethodBuilder *rmb, MonoReflectionDynamicMethod *mb)
 {
@@ -1515,6 +1567,7 @@ mono_image_add_methodimpl (MonoDynamicImage *assembly, MonoReflectionMethodBuild
        values [MONO_METHODIMPL_DECLARATION] = tok;
 }
 
+#ifndef DISABLE_REFLECTION_EMIT
 static void
 mono_image_get_method_info (MonoReflectionMethodBuilder *mb, MonoDynamicImage *assembly)
 {
@@ -1578,6 +1631,7 @@ mono_image_get_ctor_info (MonoDomain *domain, MonoReflectionCtorBuilder *mb, Mon
        mono_image_basic_method (&rmb, assembly);
        mb->table_idx = *rmb.table_idx;
 }
+#endif
 
 static char*
 type_get_fully_qualified_name (MonoType *type)
@@ -1606,11 +1660,12 @@ type_get_qualified_name (MonoType *type, MonoAssembly *ass) {
 }
 
 #ifndef DISABLE_REFLECTION_EMIT
+/*field_image is the image to which the eventual custom mods have been encoded against*/
 static guint32
-fieldref_encode_signature (MonoDynamicImage *assembly, MonoType *type)
+fieldref_encode_signature (MonoDynamicImage *assembly, MonoImage *field_image, MonoType *type)
 {
        SigBuffer buf;
-       guint32 idx, i;
+       guint32 idx, i, token;
 
        if (!assembly->save)
                return 0;
@@ -1619,14 +1674,22 @@ fieldref_encode_signature (MonoDynamicImage *assembly, MonoType *type)
        
        sigbuffer_add_value (&buf, 0x06);
        /* encode custom attributes before the type */
-       /* FIXME: This should probably go in encode_type () */
        if (type->num_mods) {
                for (i = 0; i < type->num_mods; ++i) {
+                       if (field_image) {
+                               MonoClass *class = mono_class_get (field_image, type->modifiers [i].token);
+                               g_assert (class);
+                               token = mono_image_typedef_or_ref (assembly, &class->byval_arg);
+                       } else {
+                               token = type->modifiers [i].token;
+                       }
+
                        if (type->modifiers [i].required)
                                sigbuffer_add_byte (&buf, MONO_TYPE_CMOD_REQD);
                        else
                                sigbuffer_add_byte (&buf, MONO_TYPE_CMOD_OPT);
-                       sigbuffer_add_value (&buf, type->modifiers [i].token);
+
+                       sigbuffer_add_value (&buf, token);
                }
        }
        encode_type (assembly, type, &buf);
@@ -1641,13 +1704,31 @@ field_encode_signature (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *
 {
        SigBuffer buf;
        guint32 idx;
+       guint32 typespec = 0;
+       MonoType *type;
+       MonoClass *class;
+
+       init_type_builder_generics (fb->type);
+
+       type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
+       class = mono_class_from_mono_type (type);
 
        sigbuffer_init (&buf, 32);
        
        sigbuffer_add_value (&buf, 0x06);
        encode_custom_modifiers (assembly, fb->modreq, fb->modopt, &buf);
        /* encode custom attributes before the type */
-       encode_reflection_type (assembly, monotype_cast (fb->type), &buf);
+
+       if (class->generic_container)
+               typespec = create_typespec (assembly, type);
+
+       if (typespec) {
+               MonoGenericClass *gclass;
+               gclass = mono_metadata_lookup_generic_class (class, class->generic_container->context.class_inst, TRUE);
+               encode_generic_class (assembly, gclass, &buf);
+       } else {
+               encode_type (assembly, type, &buf);
+       }
        idx = sigbuffer_add_to_blob_cached (assembly, &buf);
        sigbuffer_free (&buf);
        return idx;
@@ -1708,12 +1789,18 @@ handle_enum:
 #endif
 #endif
                break;
-       case MONO_TYPE_VALUETYPE:
-               if (val->vtable->klass->enumtype) {
-                       *ret_type = mono_class_enum_basetype (val->vtable->klass)->type;
+       case MONO_TYPE_VALUETYPE: {
+               MonoClass *klass = val->vtable->klass;
+               
+               if (klass->enumtype) {
+                       *ret_type = mono_class_enum_basetype (klass)->type;
                        goto handle_enum;
-               } else
-                       g_error ("we can't encode valuetypes");
+               } else if (mono_is_corlib_image (klass->image) && strcmp (klass->name_space, "System") == 0 && strcmp (klass->name, "DateTime") == 0) {
+                       len = 8;
+               } else 
+                       g_error ("we can't encode valuetypes, we should have never reached this line");
+               break;
+       }
        case MONO_TYPE_CLASS:
                break;
        case MONO_TYPE_STRING: {
@@ -1785,6 +1872,10 @@ encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo) {
                        }
                }
                break;
+       case MONO_NATIVE_SAFEARRAY:
+               if (minfo->eltype)
+                       sigbuffer_add_value (&buf, minfo->eltype);
+               break;
        case MONO_NATIVE_CUSTOM:
                if (minfo->guid) {
                        str = mono_string_to_utf8 (minfo->guid);
@@ -1800,7 +1891,7 @@ encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo) {
                /* custom marshaler type name */
                if (minfo->marshaltype || minfo->marshaltyperef) {
                        if (minfo->marshaltyperef)
-                               str = type_get_fully_qualified_name (monotype_cast (minfo->marshaltyperef)->type);
+                               str = type_get_fully_qualified_name (mono_reflection_type_get_handle ((MonoReflectionType*)minfo->marshaltyperef));
                        else
                                str = mono_string_to_utf8 (minfo->marshaltype);
                        len = strlen (str);
@@ -1907,23 +1998,26 @@ property_encode_signature (MonoDynamicImage *assembly, MonoReflectionPropertyBui
        if (!mb && smb && smb->parameters)
                nparams = mono_array_length (smb->parameters) - 1;
        sigbuffer_init (&buf, 32);
-       sigbuffer_add_byte (&buf, 0x08);
+       if (fb->call_conv & 0x20)
+               sigbuffer_add_byte (&buf, 0x28);
+       else
+               sigbuffer_add_byte (&buf, 0x08);
        sigbuffer_add_value (&buf, nparams);
        if (mb) {
-               encode_reflection_type (assembly, monotype_cast (mb->rtype), &buf);
+               encode_reflection_type (assembly, (MonoReflectionType*)mb->rtype, &buf);
                for (i = 0; i < nparams; ++i) {
-                       MonoReflectionType *pt = mono_type_array_get (mb->parameters, i);
+                       MonoReflectionType *pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
                        encode_reflection_type (assembly, pt, &buf);
                }
        } else if (smb && smb->parameters) {
                /* the property type is the last param */
-               encode_reflection_type (assembly, mono_type_array_get (smb->parameters, nparams), &buf);
+               encode_reflection_type (assembly, mono_array_get (smb->parameters, MonoReflectionType*, nparams), &buf);
                for (i = 0; i < nparams; ++i) {
-                       MonoReflectionType *pt = mono_type_array_get (smb->parameters, i);
+                       MonoReflectionType *pt = mono_array_get (smb->parameters, MonoReflectionType*, i);
                        encode_reflection_type (assembly, pt, &buf);
                }
        } else {
-               encode_reflection_type (assembly, monotype_cast (fb->type), &buf);
+               encode_reflection_type (assembly, (MonoReflectionType*)fb->type, &buf);
        }
 
        idx = sigbuffer_add_to_blob_cached (assembly, &buf);
@@ -1945,6 +2039,7 @@ mono_image_get_property_info (MonoReflectionPropertyBuilder *pb, MonoDynamicImag
         * PROPERTY    (rows already preallocated in _get_type_info ())
         * METHOD      (method info already done with the generic method code)
         * METHODSEMANTICS
+        * CONSTANT
         */
        table = &assembly->tables [MONO_TABLE_PROPERTY];
        pb->table_idx = table->next_idx ++;
@@ -1975,6 +2070,17 @@ mono_image_get_property_info (MonoReflectionPropertyBuilder *pb, MonoDynamicImag
                values [MONO_METHOD_SEMA_METHOD] = pb->set_method->table_idx;
                values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
        }
+       if (pb->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT) {
+               guint32 field_type = 0;
+               table = &assembly->tables [MONO_TABLE_CONSTANT];
+               table->rows ++;
+               alloc_table (table, table->rows);
+               values = table->values + table->rows * MONO_CONSTANT_SIZE;
+               values [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_PROPERTY | (pb->table_idx << MONO_HASCONSTANT_BITS);
+               values [MONO_CONSTANT_VALUE] = encode_constant (assembly, pb->def_value, &field_type);
+               values [MONO_CONSTANT_TYPE] = field_type;
+               values [MONO_CONSTANT_PADDING] = 0;
+       }
 }
 
 static void
@@ -1997,7 +2103,7 @@ mono_image_get_event_info (MonoReflectionEventBuilder *eb, MonoDynamicImage *ass
        values = table->values + eb->table_idx * MONO_EVENT_SIZE;
        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);
+       values [MONO_EVENT_TYPE] = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle (eb->type));
 
        /*
         * FIXME: we still don't handle 'other' methods 
@@ -2055,7 +2161,7 @@ encode_constraints (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynam
 
                values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
                values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (
-                       assembly, gparam->base_type->type);
+                       assembly, mono_reflection_type_get_handle (gparam->base_type));
        }
 
        for (i = 0; i < num_constraints; i++) {
@@ -2067,7 +2173,7 @@ encode_constraints (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynam
 
                values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
                values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (
-                       assembly, constraint->type);
+                       assembly, mono_reflection_type_get_handle (constraint));
        }
 }
 
@@ -2086,9 +2192,9 @@ mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 o
        entry = g_new0 (GenericParamTableEntry, 1);
        entry->owner = owner;
        /* FIXME: track where gen_params should be freed and remove the GC root as well */
-       MOVING_GC_REGISTER (&entry->gparam);
+       MONO_GC_REGISTER_ROOT_IF_MOVING (entry->gparam);
        entry->gparam = gparam;
-
+       
        g_ptr_array_add (assembly->gen_params, entry);
 }
 
@@ -2104,7 +2210,7 @@ write_generic_param_entry (MonoDynamicImage *assembly, GenericParamTableEntry *e
        table_idx = table->next_idx ++;
        values = table->values + table_idx * MONO_GENERICPARAM_SIZE;
 
-       param = entry->gparam->type.type->data.generic_param;
+       param = mono_reflection_type_get_handle ((MonoReflectionType*)entry->gparam)->data.generic_param;
 
        values [MONO_GENERICPARAM_OWNER] = entry->owner;
        values [MONO_GENERICPARAM_FLAGS] = entry->gparam->attrs;
@@ -2261,9 +2367,9 @@ mono_image_typedef_or_ref_full (MonoDynamicImage *assembly, MonoType *type, gboo
         */
        if ((klass->image == &assembly->image) && (type->type != MONO_TYPE_VAR) && 
                        (type->type != MONO_TYPE_MVAR)) {
-               MonoReflectionTypeBuilder *tb = klass->reflection_info;
+               MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
                token = MONO_TYPEDEFORREF_TYPEDEF | (tb->table_idx << MONO_TYPEDEFORREF_BITS);
-               mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), klass->reflection_info);
+               mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), mono_class_get_ref_info (klass));
                return token;
        }
 
@@ -2286,7 +2392,7 @@ mono_image_typedef_or_ref_full (MonoDynamicImage *assembly, MonoType *type, gboo
        token = MONO_TYPEDEFORREF_TYPEREF | (table->next_idx << MONO_TYPEDEFORREF_BITS); /* typeref */
        g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
        table->next_idx ++;
-       mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), klass->reflection_info);
+       mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), mono_class_get_ref_info (klass));
        return token;
 }
 
@@ -2300,21 +2406,13 @@ mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type)
 }
 
 #ifndef DISABLE_REFLECTION_EMIT
-/*
- * Insert a memberef row into the metadata: the token that point to the memberref
- * is returned. Caching is done in the caller (mono_image_get_methodref_token() or
- * mono_image_get_fieldref_token()).
- * The sig param is an index to an already built signature.
- */
 static guint32
-mono_image_get_memberref_token (MonoDynamicImage *assembly, MonoType *type, const char *name, guint32 sig)
+mono_image_add_memberef_row (MonoDynamicImage *assembly, guint32 parent, const char *name, guint32 sig)
 {
        MonoDynamicTable *table;
        guint32 *values;
        guint32 token, pclass;
-       guint32 parent;
 
-       parent = mono_image_typedef_or_ref (assembly, type);
        switch (parent & MONO_TYPEDEFORREF_MASK) {
        case MONO_TYPEDEFORREF_TYPEREF:
                pclass = MONO_MEMBERREF_PARENT_TYPEREF;
@@ -2348,6 +2446,20 @@ mono_image_get_memberref_token (MonoDynamicImage *assembly, MonoType *type, cons
        return token;
 }
 
+/*
+ * Insert a memberef row into the metadata: the token that point to the memberref
+ * is returned. Caching is done in the caller (mono_image_get_methodref_token() or
+ * mono_image_get_fieldref_token()).
+ * The sig param is an index to an already built signature.
+ */
+static guint32
+mono_image_get_memberref_token (MonoDynamicImage *assembly, MonoType *type, const char *name, guint32 sig)
+{
+       guint32 parent = mono_image_typedef_or_ref (assembly, type);
+       return mono_image_add_memberef_row (assembly, parent, name, sig);
+}
+
+
 static guint32
 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method, gboolean create_typespec)
 {
@@ -2406,9 +2518,10 @@ mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method,
 static guint32
 mono_image_get_methodref_token_for_methodbuilder (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *method)
 {
-       guint32 token;
+       guint32 token, parent, sig;
        ReflectionMethodBuilder rmb;
        char *name;
+       MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)method->type;
        
        token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
        if (token)
@@ -2423,8 +2536,15 @@ mono_image_get_methodref_token_for_methodbuilder (MonoDynamicImage *assembly, Mo
        */
        if ((rmb.call_conv & ~0x60) != MONO_CALL_DEFAULT && (rmb.call_conv & ~0x60) != MONO_CALL_VARARG)
                rmb.call_conv = (rmb.call_conv & 0x60) | MONO_CALL_DEFAULT;
-       token = mono_image_get_memberref_token (assembly, ((MonoReflectionTypeBuilder*)rmb.type)->type.type,
-                                       name, method_builder_encode_signature (assembly, &rmb));
+
+       sig = method_builder_encode_signature (assembly, &rmb);
+
+       if (tb->generic_params)
+               parent = create_generic_typespec (assembly, tb);
+       else
+               parent = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)rmb.type));
+
+       token = mono_image_add_memberef_row (assembly, parent, name, sig);
 
        g_free (name);
        g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
@@ -2524,38 +2644,45 @@ static guint32
 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, gboolean create_methodspec)
 {
        guint32 token;
-       
+
        if (mb->generic_params && create_methodspec) 
                return mono_image_get_methodspec_token_for_generic_method_definition (assembly, mb);
 
-       token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, mb));
+       token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, mb));
        if (token)
                return token;
 
        token = mono_image_get_methodref_token_for_methodbuilder (assembly, mb);
-       g_hash_table_insert (assembly->handleref, mb, GUINT_TO_POINTER(token));
+       mono_g_hash_table_insert (assembly->handleref_managed, mb, GUINT_TO_POINTER(token));
        return token;
 }
 
 static guint32
 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *mb)
 {
-       guint32 token;
+       guint32 token, parent, sig;
        ReflectionMethodBuilder rmb;
        char *name;
+       MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
        
-       token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, mb));
+       token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, mb));
        if (token)
                return token;
 
        reflection_methodbuilder_from_ctor_builder (&rmb, mb);
 
+       if (tb->generic_params)
+               parent = create_generic_typespec (assembly, tb);
+       else
+               parent = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)tb));
+       
        name = mono_string_to_utf8 (rmb.name);
-       token = mono_image_get_memberref_token (assembly, ((MonoReflectionTypeBuilder*)rmb.type)->type.type,
-               name, method_builder_encode_signature (assembly, &rmb));
+       sig = method_builder_encode_signature (assembly, &rmb);
+
+       token = mono_image_add_memberef_row (assembly, parent, name, sig);
 
        g_free (name);
-       g_hash_table_insert (assembly->handleref, mb, GUINT_TO_POINTER(token));
+       mono_g_hash_table_insert (assembly->handleref_managed, mb, GUINT_TO_POINTER(token));
        return token;
 }
 #endif
@@ -2572,45 +2699,58 @@ is_field_on_inst (MonoClassField *field)
 static MonoType*
 get_field_on_inst_generic_type (MonoClassField *field)
 {
+       MonoClass *class, *gtd;
        MonoDynamicGenericClass *dgclass;
        int field_index;
 
        g_assert (is_field_on_inst (field));
 
        dgclass = (MonoDynamicGenericClass*)field->parent->generic_class;
-       field_index = field - dgclass->fields;
 
-       g_assert (field_index >= 0 && field_index < dgclass->count_fields);
-       return dgclass->field_generic_types [field_index];
+       if (field >= dgclass->fields && field - dgclass->fields < dgclass->count_fields) {
+               field_index = field - dgclass->fields;
+               return dgclass->field_generic_types [field_index];              
+       }
+
+       class = field->parent;
+       gtd = class->generic_class->container_class;
+
+       if (field >= class->fields && field - class->fields < class->field.count) {
+               field_index = field - class->fields;
+               return gtd->fields [field_index].type;
+       }
+
+       g_assert_not_reached ();
+       return 0;
 }
 
 #ifndef DISABLE_REFLECTION_EMIT
 static guint32
-mono_image_get_fieldref_token (MonoDynamicImage *assembly, MonoReflectionField *f)
+mono_image_get_fieldref_token (MonoDynamicImage *assembly, MonoObject *f, MonoClassField *field)
 {
        MonoType *type;
        guint32 token;
-       MonoClassField *field;
 
-       token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, f));
+       g_assert (field);
+       g_assert (field->parent);
+
+       token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, f));
        if (token)
                return token;
-       g_assert (f->field->parent);
 
-       field = f->field;
        if (field->parent->generic_class && field->parent->generic_class->container_class && field->parent->generic_class->container_class->fields) {
                int index = field - field->parent->fields;
                type = field->parent->generic_class->container_class->fields [index].type;
        } else {
-               if (is_field_on_inst (f->field))
-                       type = get_field_on_inst_generic_type (f->field);
+               if (is_field_on_inst (field))
+                       type = get_field_on_inst_generic_type (field);
                else
-                       type = f->field->type;
+                       type = field->type;
        }
-       token = mono_image_get_memberref_token (assembly, &f->field->parent->byval_arg, 
-                                                                                       mono_field_get_name (f->field),  
-                                                                                       fieldref_encode_signature (assembly, type));
-       g_hash_table_insert (assembly->handleref, f, GUINT_TO_POINTER(token));
+       token = mono_image_get_memberref_token (assembly, &field->parent->byval_arg,
+                                                                                       mono_field_get_name (field),
+                                                                                       fieldref_encode_signature (assembly, field->parent->image, type));
+       mono_g_hash_table_insert (assembly->handleref_managed, f, GUINT_TO_POINTER(token));
        return token;
 }
 
@@ -2621,22 +2761,39 @@ mono_image_get_field_on_inst_token (MonoDynamicImage *assembly, MonoReflectionFi
        MonoClass *klass;
        MonoGenericClass *gclass;
        MonoDynamicGenericClass *dgclass;
-       MonoReflectionFieldBuilder *fb = f->fb;
+       MonoType *type;
        char *name;
 
-       token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, f));
+       token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, f));
        if (token)
                return token;
-       klass = mono_class_from_mono_type (f->inst->type.type);
-       gclass = f->inst->type.type->data.generic_class;
-       g_assert (gclass->is_dynamic);
-       dgclass = (MonoDynamicGenericClass *) gclass;
+       if (is_sre_field_builder (mono_object_class (f->fb))) {
+               MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)f->fb;
+               type = mono_reflection_type_get_handle ((MonoReflectionType*)f->inst);
+               klass = mono_class_from_mono_type (type);
+               gclass = type->data.generic_class;
+               g_assert (gclass->is_dynamic);
+               dgclass = (MonoDynamicGenericClass *) gclass;
+
+               name = mono_string_to_utf8 (fb->name);
+               token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, 
+                                                                                               field_encode_signature (assembly, fb));
+               g_free (name);          
+       } else if (is_sr_mono_field (mono_object_class (f->fb))) {
+               guint32 sig;
+               MonoClassField *field = ((MonoReflectionField *)f->fb)->field;
+
+               type = mono_reflection_type_get_handle ((MonoReflectionType*)f->inst);
+               klass = mono_class_from_mono_type (type);
 
-       name = mono_string_to_utf8 (fb->name);
-       token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, 
-                                                                                       field_encode_signature (assembly, fb));
-       g_free (name);
-       g_hash_table_insert (assembly->handleref, f, GUINT_TO_POINTER (token));
+               sig = fieldref_encode_signature (assembly, field->parent->image, field->type);
+               token = mono_image_get_memberref_token (assembly, &klass->byval_arg, field->name, sig);
+       } else {
+               char *name = mono_type_get_full_name (mono_object_class (f->fb));
+               g_error ("mono_image_get_field_on_inst_token: don't know how to handle %s", name);
+       }
+
+       mono_g_hash_table_insert (assembly->handleref_managed, f, GUINT_TO_POINTER (token));
        return token;
 }
 
@@ -2646,65 +2803,147 @@ mono_image_get_ctor_on_inst_token (MonoDynamicImage *assembly, MonoReflectionCto
        guint32 sig, token;
        MonoClass *klass;
        MonoGenericClass *gclass;
-       MonoDynamicGenericClass *dgclass;
-       MonoReflectionCtorBuilder *cb = c->cb;
-       ReflectionMethodBuilder rmb;
-       char *name;
+       MonoType *type;
 
        /* A ctor cannot be a generic method, so we can ignore create_methodspec */
 
-       token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, c));
+       token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, c));
        if (token)
                return token;
-       klass = mono_class_from_mono_type (c->inst->type.type);
-       gclass = c->inst->type.type->data.generic_class;
-       g_assert (gclass->is_dynamic);
-       dgclass = (MonoDynamicGenericClass *) gclass;
 
-       reflection_methodbuilder_from_ctor_builder (&rmb, cb);
+       if (is_sre_ctor_builder (mono_object_class (c->cb))) {
+               MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder *)c->cb;
+               MonoDynamicGenericClass *dgclass;
+               ReflectionMethodBuilder rmb;
+               char *name;
+
+               type = mono_reflection_type_get_handle ((MonoReflectionType*)c->inst);
+               klass = mono_class_from_mono_type (type);
 
-       name = mono_string_to_utf8 (rmb.name);
+               gclass = type->data.generic_class;
+               g_assert (gclass->is_dynamic);
+               dgclass = (MonoDynamicGenericClass *) gclass;
 
-       sig = method_builder_encode_signature (assembly, &rmb);
+               reflection_methodbuilder_from_ctor_builder (&rmb, cb);
+
+               name = mono_string_to_utf8 (rmb.name);
+
+               sig = method_builder_encode_signature (assembly, &rmb);
+
+               token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig);
+               g_free (name);
+       } else if (is_sr_mono_cmethod (mono_object_class (c->cb))) {
+               MonoMethod *mm = ((MonoReflectionMethod *)c->cb)->method;
+
+               type = mono_reflection_type_get_handle ((MonoReflectionType*)c->inst);
+               klass = mono_class_from_mono_type (type);
+
+               sig = method_encode_signature (assembly, mono_method_signature (mm));
+               token = mono_image_get_memberref_token (assembly, &klass->byval_arg, mm->name, sig);
+       } else {
+               char *name = mono_type_get_full_name (mono_object_class (c->cb));
+               g_error ("mono_image_get_method_on_inst_token: don't know how to handle %s", name);
+       }
 
-       token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig);
-       g_free (name);
 
-       g_hash_table_insert (assembly->handleref, c, GUINT_TO_POINTER (token));
+       mono_g_hash_table_insert (assembly->handleref_managed, c, GUINT_TO_POINTER (token));
        return token;
 }
 
+static MonoMethod*
+mono_reflection_method_on_tb_inst_get_handle (MonoReflectionMethodOnTypeBuilderInst *m)
+{
+       MonoClass *klass;
+       MonoGenericContext tmp_context;
+       MonoType **type_argv;
+       MonoGenericInst *ginst;
+       MonoMethod *method, *inflated;
+       int count, i;
+
+       init_type_builder_generics ((MonoObject*)m->inst);
+
+       method = inflate_method (m->inst, (MonoObject*)m->mb);
+
+       klass = method->klass;
+
+       if (m->method_args == NULL)
+               return method;
+
+       if (method->is_inflated)
+               method = ((MonoMethodInflated *) method)->declaring;
+
+       count = mono_array_length (m->method_args);
+
+       type_argv = g_new0 (MonoType *, count);
+       for (i = 0; i < count; i++) {
+               MonoReflectionType *garg = mono_array_get (m->method_args, gpointer, i);
+               type_argv [i] = mono_reflection_type_get_handle (garg);
+       }
+       ginst = mono_metadata_get_generic_inst (count, type_argv);
+       g_free (type_argv);
+
+       tmp_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL;
+       tmp_context.method_inst = ginst;
+
+       inflated = mono_class_inflate_generic_method (method, &tmp_context);
+       return inflated;
+}
+
 static guint32
 mono_image_get_method_on_inst_token (MonoDynamicImage *assembly, MonoReflectionMethodOnTypeBuilderInst *m, gboolean create_methodspec)
 {
-       guint32 sig, token;
+       guint32 sig, token = 0;
+       MonoType *type;
        MonoClass *klass;
-       MonoGenericClass *gclass;
-       MonoReflectionMethodBuilder *mb = m->mb;
-       ReflectionMethodBuilder rmb;
-       char *name;
 
-       if (create_methodspec && mb->generic_params)
-               // FIXME:
-               g_assert_not_reached ();
+       if (m->method_args) {
+               MonoMethod *inflated;
+
+               inflated = mono_reflection_method_on_tb_inst_get_handle (m);
+               if (create_methodspec)
+                       token = mono_image_get_methodspec_token (assembly, inflated);
+               else
+                       token = mono_image_get_inflated_method_token (assembly, inflated);
+               return token;
+       }
 
-       token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, m));
+       token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, m));
        if (token)
                return token;
-       klass = mono_class_from_mono_type (m->inst->type.type);
-       gclass = m->inst->type.type->data.generic_class;
-       g_assert (gclass->is_dynamic);
 
-       reflection_methodbuilder_from_method_builder (&rmb, mb);
+       if (is_sre_method_builder (mono_object_class (m->mb))) {
+               MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)m->mb;
+               MonoGenericClass *gclass;
+               ReflectionMethodBuilder rmb;
+               char *name;
 
-       name = mono_string_to_utf8 (rmb.name);
+               type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst);
+               klass = mono_class_from_mono_type (type);
+               gclass = type->data.generic_class;
+               g_assert (gclass->is_dynamic);
 
-       sig = method_builder_encode_signature (assembly, &rmb);
+               reflection_methodbuilder_from_method_builder (&rmb, mb);
 
-       token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig);
-       g_free (name);
+               name = mono_string_to_utf8 (rmb.name);
+
+               sig = method_builder_encode_signature (assembly, &rmb);
+
+               token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig);
+               g_free (name);          
+       } else if (is_sr_mono_method (mono_object_class (m->mb))) {
+               MonoMethod *mm = ((MonoReflectionMethod *)m->mb)->method;
+
+               type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst);
+               klass = mono_class_from_mono_type (type);
+
+               sig = method_encode_signature (assembly, mono_method_signature (mm));
+               token = mono_image_get_memberref_token (assembly, &klass->byval_arg, mm->name, sig);
+       } else {
+               char *name = mono_type_get_full_name (mono_object_class (m->mb));
+               g_error ("mono_image_get_method_on_inst_token: don't know how to handle %s", name);
+       }
 
-       g_hash_table_insert (assembly->handleref, m, GUINT_TO_POINTER (token));
+       mono_g_hash_table_insert (assembly->handleref_managed, m, GUINT_TO_POINTER (token));
        return token;
 }
 
@@ -2825,6 +3064,7 @@ create_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *
 {
        MonoDynamicTable *table;
        MonoClass *klass;
+       MonoType *type;
        guint32 *values;
        guint32 token;
        SigBuffer buf;
@@ -2835,15 +3075,15 @@ create_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *
         * ie. what we'd normally use as the generic type in a TypeSpec signature.
         * Because of this, we must not insert it into the `typeref' hash table.
         */
-
-       token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, tb->type.type));
+       type = mono_reflection_type_get_handle ((MonoReflectionType*)tb);
+       token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, type));
        if (token)
                return token;
 
        sigbuffer_init (&buf, 32);
 
        g_assert (tb->generic_params);
-       klass = mono_class_from_mono_type (tb->type.type);
+       klass = mono_class_from_mono_type (type);
 
        if (tb->generic_container)
                mono_reflection_create_generic_class (tb);
@@ -2860,7 +3100,7 @@ create_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *
 
                gparam = mono_array_get (tb->generic_params, MonoReflectionGenericParam *, i);
 
-               encode_type (assembly, gparam->type.type, &buf);
+               encode_type (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)gparam), &buf);
        }
 
        table = &assembly->tables [MONO_TABLE_TYPESPEC];
@@ -2874,7 +3114,7 @@ create_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *
        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));
+       g_hash_table_insert (assembly->typespec, type, GUINT_TO_POINTER(token));
        table->next_idx ++;
        return token;
 }
@@ -2897,25 +3137,25 @@ add_custom_modifiers (MonoDynamicImage *assembly, MonoType *type, MonoArray *mod
        if (count == 0)
                return mono_metadata_type_dup (NULL, type);
 
-       len = sizeof (MonoType) + ((gint32)count - MONO_ZERO_LEN_ARRAY) * sizeof (MonoCustomMod);
+       len = MONO_SIZEOF_TYPE + ((gint32)count) * sizeof (MonoCustomMod);
        t = g_malloc (len);
-       memcpy (t, type, sizeof (MonoType));
+       memcpy (t, type, MONO_SIZEOF_TYPE);
 
        t->num_mods = count;
        pos = 0;
        if (modreq) {
                for (i = 0; i < mono_array_length (modreq); ++i) {
-                       MonoReflectionType *mod = mono_type_array_get (modreq, i);
+                       MonoType *mod = mono_type_array_get_and_resolve (modreq, i);
                        t->modifiers [pos].required = 1;
-                       t->modifiers [pos].token = mono_image_typedef_or_ref (assembly, mod->type);
+                       t->modifiers [pos].token = mono_image_typedef_or_ref (assembly, mod);
                        pos ++;
                }
        }
        if (modopt) {
                for (i = 0; i < mono_array_length (modopt); ++i) {
-                       MonoReflectionType *mod = mono_type_array_get (modopt, i);
+                       MonoType *mod = mono_type_array_get_and_resolve (modopt, i);
                        t->modifiers [pos].required = 0;
-                       t->modifiers [pos].token = mono_image_typedef_or_ref (assembly, mod->type);
+                       t->modifiers [pos].token = mono_image_typedef_or_ref (assembly, mod);
                        pos ++;
                }
        }
@@ -2923,32 +3163,47 @@ add_custom_modifiers (MonoDynamicImage *assembly, MonoType *type, MonoArray *mod
        return t;
 }
 
+static void
+init_type_builder_generics (MonoObject *type)
+{
+       MonoReflectionTypeBuilder *tb;
+
+       if (!is_sre_type_builder(mono_object_class (type)))
+               return;
+       tb = (MonoReflectionTypeBuilder *)type;
+
+       if (tb && tb->generic_container)
+               mono_reflection_create_generic_class (tb);
+}
+
 static guint32
 mono_image_get_generic_field_token (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
 {
        MonoDynamicTable *table;
        MonoClass *klass;
-       MonoType *custom = NULL;
+       MonoType *custom = NULL, *type;
        guint32 *values;
        guint32 token, pclass, parent, sig;
        gchar *name;
 
-       token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, fb));
+       token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, fb));
        if (token)
                return token;
 
-       klass = mono_class_from_mono_type (fb->typeb->type);
+       klass = mono_class_from_mono_type (mono_reflection_type_get_handle (fb->typeb));
        name = mono_string_to_utf8 (fb->name);
 
+       /*FIXME this is one more layer of ugliness due how types are created.*/
+       init_type_builder_generics (fb->type);
+
        /* fb->type does not include the custom modifiers */
        /* FIXME: We should do this in one place when a fieldbuilder is created */
-       if (fb->modreq || fb->modopt) {
-               custom = add_custom_modifiers (assembly, monotype_cast (fb->type)->type, fb->modreq, fb->modopt);
-               sig = fieldref_encode_signature (assembly, custom);
-               g_free (custom);
-       } else {
-               sig = fieldref_encode_signature (assembly, monotype_cast (fb->type)->type);
-       }
+       type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
+       if (fb->modreq || fb->modopt)
+               type = custom = add_custom_modifiers (assembly, type, fb->modreq, fb->modopt);
+
+       sig = fieldref_encode_signature (assembly, NULL, type);
+       g_free (custom);
 
        parent = create_generic_typespec (assembly, (MonoReflectionTypeBuilder *) fb->typeb);
        g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_TYPEDEFORREF_TYPESPEC);
@@ -2968,7 +3223,7 @@ mono_image_get_generic_field_token (MonoDynamicImage *assembly, MonoReflectionFi
 
        token = MONO_TOKEN_MEMBER_REF | table->next_idx;
        table->next_idx ++;
-       g_hash_table_insert (assembly->handleref, fb, GUINT_TO_POINTER(token));
+       mono_g_hash_table_insert (assembly->handleref_managed, fb, GUINT_TO_POINTER(token));
        g_free (name);
        return token;
 }
@@ -3027,7 +3282,7 @@ mono_reflection_encode_sighelper (MonoDynamicImage *assembly, MonoReflectionSigH
                        modopts = mono_array_get (helper->modopts, MonoArray*, i);
 
                encode_custom_modifiers (assembly, modreqs, modopts, &buf);
-               pt = mono_type_array_get (helper->arguments, i);
+               pt = mono_array_get (helper->arguments, MonoReflectionType*, i);
                encode_reflection_type (assembly, pt, &buf);
        }
        idx = sigbuffer_add_to_blob_cached (assembly, &buf);
@@ -3084,24 +3339,24 @@ mono_image_get_array_token (MonoDynamicImage *assembly, MonoReflectionArrayMetho
        char *name;
        MonoMethodSignature *sig;
        ArrayMethod *am;
-       
+       MonoType *mtype;
+
        name = mono_string_to_utf8 (m->name);
        nparams = mono_array_length (m->parameters);
-       sig = g_malloc0 (sizeof (MonoMethodSignature) + sizeof (MonoType*) * nparams);
+       sig = g_malloc0 (MONO_SIZEOF_METHOD_SIGNATURE + sizeof (MonoType*) * nparams);
        sig->hasthis = 1;
        sig->sentinelpos = -1;
        sig->call_convention = reflection_cc_to_file (m->call_conv);
        sig->param_count = nparams;
-       sig->ret = m->ret? m->ret->type: &mono_defaults.void_class->byval_arg;
-       for (i = 0; i < nparams; ++i) {
-               MonoReflectionType *t = mono_type_array_get (m->parameters, i);
-               sig->params [i] = t->type;
-       }
+       sig->ret = m->ret ? mono_reflection_type_get_handle (m->ret): &mono_defaults.void_class->byval_arg;
+       mtype = mono_reflection_type_get_handle (m->parent);
+       for (i = 0; i < nparams; ++i)
+               sig->params [i] = mono_type_array_get_and_resolve (m->parameters, i);
 
        for (tmp = assembly->array_methods; tmp; tmp = tmp->next) {
                am = tmp->data;
                if (strcmp (name, am->name) == 0 && 
-                               mono_metadata_type_equal (am->parent, m->parent->type) &&
+                               mono_metadata_type_equal (am->parent, mtype) &&
                                mono_metadata_signature_equal (am->sig, sig)) {
                        g_free (name);
                        g_free (sig);
@@ -3112,14 +3367,13 @@ mono_image_get_array_token (MonoDynamicImage *assembly, MonoReflectionArrayMetho
        am = g_new0 (ArrayMethod, 1);
        am->name = name;
        am->sig = sig;
-       am->parent = m->parent->type;
+       am->parent = mtype;
        am->token = mono_image_get_memberref_token (assembly, am->parent, name,
                method_encode_signature (assembly, sig));
        assembly->array_methods = g_list_prepend (assembly->array_methods, am);
        m->table_idx = am->token & 0xffffff;
        return am->token;
 }
-#endif
 
 /*
  * Insert into the metadata tables all the info about the TypeBuilder tb.
@@ -3148,7 +3402,7 @@ mono_image_get_type_info (MonoDomain *domain, MonoReflectionTypeBuilder *tb, Mon
        g_free (n);
        if (tb->parent && !(is_system && is_object) && 
                        !(tb->attrs & TYPE_ATTRIBUTE_INTERFACE)) { /* interfaces don't have a parent */
-               values [MONO_TYPEDEF_EXTENDS] = mono_image_typedef_or_ref (assembly, monotype_cast (tb->parent)->type);
+               values [MONO_TYPEDEF_EXTENDS] = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent));
        } else {
                values [MONO_TYPEDEF_EXTENDS] = 0;
        }
@@ -3180,7 +3434,7 @@ mono_image_get_type_info (MonoDomain *domain, MonoReflectionTypeBuilder *tb, Mon
                for (i = 0; i < mono_array_length (tb->interfaces); ++i) {
                        MonoReflectionType* iface = (MonoReflectionType*) mono_array_get (tb->interfaces, gpointer, i);
                        values [MONO_INTERFACEIMPL_CLASS] = tb->table_idx;
-                       values [MONO_INTERFACEIMPL_INTERFACE] = mono_image_typedef_or_ref (assembly, iface->type);
+                       values [MONO_INTERFACEIMPL_INTERFACE] = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle (iface));
                        values += MONO_INTERFACEIMPL_SIZE;
                }
        }
@@ -3283,13 +3537,14 @@ mono_image_get_type_info (MonoDomain *domain, MonoReflectionTypeBuilder *tb, Mon
                }
        }
 }
+#endif
 
 static void
-collect_types (GPtrArray *types, MonoReflectionTypeBuilder *type)
+collect_types (MonoPtrArray *types, MonoReflectionTypeBuilder *type)
 {
        int i;
 
-       g_ptr_array_add (types, type); /* FIXME: GC object added to unmanaged memory */
+       mono_ptr_array_append (*types, type);
 
        if (!type->subtypes)
                return;
@@ -3504,7 +3759,7 @@ mono_image_fill_export_table (MonoDomain *domain, MonoReflectionTypeBuilder *tb,
        MonoClass *klass;
        guint32 idx, i;
 
-       klass = mono_class_from_mono_type (tb->type.type);
+       klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
 
        klass->type_token = mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx);
 
@@ -3539,29 +3794,32 @@ mono_image_fill_export_table_from_module (MonoDomain *domain, MonoReflectionModu
        }
 }
 
-static guint32
-add_exported_type (MonoReflectionAssemblyBuilder *assemblyb, MonoDynamicImage *assembly, MonoClass *klass)
+static void
+add_exported_type (MonoReflectionAssemblyBuilder *assemblyb, MonoDynamicImage *assembly, MonoClass *klass, guint32 parent_index)
 {
        MonoDynamicTable *table;
        guint32 *values;
-       guint32 scope, idx, res, impl;
+       guint32 scope, scope_idx, impl, current_idx;
        gboolean forwarder = TRUE;
+       gpointer iter = NULL;
+       MonoClass *nested;
 
        if (klass->nested_in) {
-               impl = add_exported_type (assemblyb, assembly, klass->nested_in);
+               impl = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
                forwarder = FALSE;
        } else {
                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;
-               impl = (idx << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_ASSEMBLYREF;
+               scope_idx = scope >> MONO_RESOLTION_SCOPE_BITS;
+               impl = (scope_idx << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_ASSEMBLYREF;
        }
 
        table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
 
        table->rows++;
        alloc_table (table, table->rows);
-       values = table->values + table->next_idx * MONO_EXP_TYPE_SIZE;
+       current_idx = table->next_idx;
+       values = table->values + current_idx * MONO_EXP_TYPE_SIZE;
 
        values [MONO_EXP_TYPE_FLAGS] = forwarder ? TYPE_ATTRIBUTE_FORWARDER : 0;
        values [MONO_EXP_TYPE_TYPEDEF] = 0;
@@ -3569,11 +3827,10 @@ add_exported_type (MonoReflectionAssemblyBuilder *assemblyb, MonoDynamicImage *a
        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);
 
-       res = (table->next_idx << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
-
        table->next_idx++;
 
-       return res;
+       while ((nested = mono_class_get_nested_types (klass, &iter)))
+               add_exported_type (assemblyb, assembly, nested, current_idx);
 }
 
 static void
@@ -3586,15 +3843,17 @@ mono_image_fill_export_table_from_type_forwarders (MonoReflectionAssemblyBuilder
                return;
 
        for (i = 0; i < mono_array_length (assemblyb->type_forwarders); ++i) {
-               MonoReflectionType *t = mono_type_array_get (assemblyb->type_forwarders, i);
+               MonoReflectionType *t = mono_array_get (assemblyb->type_forwarders, MonoReflectionType *, i);
+               MonoType *type;
                if (!t)
                        continue;
 
-               g_assert (t->type);
+               type = mono_reflection_type_get_handle (t);
+               g_assert (type);
 
-               klass = mono_class_from_mono_type (t->type);
+               klass = mono_class_from_mono_type (type);
 
-               add_exported_type (assemblyb, assembly, klass);
+               add_exported_type (assemblyb, assembly, klass, 0);
        }
 }
 
@@ -3659,8 +3918,8 @@ compare_genericparam (const void *a, const void *b)
 
        if ((*b_entry)->owner == (*a_entry)->owner)
                return 
-                       mono_type_get_generic_param_num ((*a_entry)->gparam->type.type) -
-                       mono_type_get_generic_param_num ((*b_entry)->gparam->type.type);
+                       mono_type_get_generic_param_num (mono_reflection_type_get_handle ((MonoReflectionType*)(*a_entry)->gparam)) -
+                       mono_type_get_generic_param_num (mono_reflection_type_get_handle ((MonoReflectionType*)(*b_entry)->gparam));
        else
                return (*a_entry)->owner - (*b_entry)->owner;
 }
@@ -3839,13 +4098,8 @@ build_compressed_metadata (MonoDynamicImage *assembly)
        *int32val = GUINT32_TO_LE (0); /* reserved */
        p += 4;
 
-       if (mono_framework_version () > 1) {
-               *p++ = 2; /* version */
-               *p++ = 0;
-       } else {
-               *p++ = 1; /* version */
-               *p++ = 0;
-       }
+       *p++ = 2; /* version */
+       *p++ = 0;
 
        if (meta->idx_string_wide)
                *p |= 0x01;
@@ -4030,6 +4284,8 @@ fixup_method (MonoReflectionILGen *ilgen, gpointer value, MonoDynamicImage *asse
                                continue;
                        } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
                                continue;
+                       } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodOnTypeBuilderInst")) {
+                               continue;
                        } else {
                                g_assert_not_reached ();
                        }
@@ -4316,7 +4572,7 @@ mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb)
        MonoDynamicImage *assembly;
        MonoReflectionAssemblyBuilder *assemblyb;
        MonoDomain *domain;
-       GPtrArray *types;
+       MonoPtrArray types;
        guint32 *values;
        int i, j;
 
@@ -4374,34 +4630,34 @@ mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb)
        mono_image_fill_module_table (domain, moduleb, assembly);
 
        /* Collect all types into a list sorted by their table_idx */
-       types = g_ptr_array_new ();
+       mono_ptr_array_init (types, moduleb->num_types);
 
        if (moduleb->types)
                for (i = 0; i < moduleb->num_types; ++i) {
                        MonoReflectionTypeBuilder *type = mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i);
-                       collect_types (types, type);
+                       collect_types (&types, type);
                }
 
-       g_ptr_array_sort (types, (GCompareFunc)compare_types_by_table_idx);
+       mono_ptr_array_sort (types, (gpointer)compare_types_by_table_idx);
        table = &assembly->tables [MONO_TABLE_TYPEDEF];
-       table->rows += types->len;
+       table->rows += mono_ptr_array_size (types);
        alloc_table (table, table->rows);
 
        /*
         * 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);
+       for (i = 0; i < mono_ptr_array_size (types); ++i) {
+               MonoReflectionTypeBuilder *tb = mono_ptr_array_get (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);
+       for (i = 0; i < mono_ptr_array_size (types); ++i) {
+               MonoReflectionTypeBuilder *tb = mono_ptr_array_get (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);
+       for (i = 0; i < mono_ptr_array_size (types); ++i) {
+               MonoReflectionTypeBuilder *type = mono_ptr_array_get (types, i);
                mono_image_get_type_info (domain, type, assembly);
        }
 
@@ -4435,8 +4691,8 @@ mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb)
                }
        }
 
-       for (i = 0; i < types->len; ++i) {
-               MonoReflectionTypeBuilder *type = g_ptr_array_index (types, i);
+       for (i = 0; i < mono_ptr_array_size (types); ++i) {
+               MonoReflectionTypeBuilder *type = mono_ptr_array_get (types, i);
                if (type->methods) {
                        for (j = 0; j < type->num_methods; ++j) {
                                MonoReflectionMethodBuilder *mb = mono_array_get (
@@ -4447,7 +4703,7 @@ mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb)
                }
        }
 
-       g_ptr_array_free (types, TRUE);
+       mono_ptr_array_destroy (types);
 
        fixup_cattrs (assembly);
 }
@@ -4530,11 +4786,12 @@ mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, Mon
 {
        MonoClass *klass;
        guint32 token = 0;
+       MonoMethodSignature *sig;
 
        klass = obj->vtable->klass;
        if (strcmp (klass->name, "MonoMethod") == 0) {
                MonoMethod *method = ((MonoReflectionMethod *)obj)->method;
-               MonoMethodSignature *sig, *old;
+               MonoMethodSignature *old;
                guint32 sig_token, parent;
                int nargs, i;
 
@@ -4557,7 +4814,7 @@ mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, Mon
 
                for (i = 0; i < nargs; i++) {
                        MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
-                       sig->params [old->param_count + i] = rt->type;
+                       sig->params [old->param_count + i] = mono_reflection_type_get_handle (rt);
                }
 
                parent = mono_image_typedef_or_ref (assembly, &method->klass->byval_arg);
@@ -4572,13 +4829,37 @@ mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, Mon
        } else if (strcmp (klass->name, "MethodBuilder") == 0) {
                MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
                ReflectionMethodBuilder rmb;
-               guint32 parent, sig;
+               guint32 parent, sig_token;
+               int nopt_args, nparams, ngparams, i;
                char *name;
 
                reflection_methodbuilder_from_method_builder (&rmb, mb);
                rmb.opt_types = opt_param_types;
+               nopt_args = mono_array_length (opt_param_types);
 
-               sig = method_builder_encode_signature (assembly, &rmb);
+               nparams = rmb.parameters ? mono_array_length (rmb.parameters): 0;
+               ngparams = rmb.generic_params ? mono_array_length (rmb.generic_params): 0;
+               sig = mono_metadata_signature_alloc (&assembly->image, nparams + nopt_args);
+
+               sig->hasthis = !(rmb.attrs & METHOD_ATTRIBUTE_STATIC);
+               sig->explicit_this = (rmb.call_conv & 0x40) == 0x40;
+               sig->call_convention = rmb.call_conv;
+               sig->generic_param_count = ngparams;
+               sig->param_count = nparams + nopt_args;
+               sig->sentinelpos = nparams;
+               sig->ret = mono_reflection_type_get_handle (rmb.rtype);
+
+               for (i = 0; i < nparams; i++) {
+                       MonoReflectionType *rt = mono_array_get (rmb.parameters, MonoReflectionType *, i);
+                       sig->params [i] = mono_reflection_type_get_handle (rt);
+               }
+
+               for (i = 0; i < nopt_args; i++) {
+                       MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
+                       sig->params [nparams + i] = mono_reflection_type_get_handle (rt);
+               }
+
+               sig_token = method_builder_encode_signature (assembly, &rmb);
 
                parent = mono_image_create_token (assembly, obj, TRUE, TRUE);
                g_assert (mono_metadata_token_table (parent) == MONO_TABLE_METHOD);
@@ -4588,12 +4869,14 @@ mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, Mon
 
                name = mono_string_to_utf8 (rmb.name);
                token = mono_image_get_varargs_method_token (
-                       assembly, parent, name, sig);
+                       assembly, parent, name, sig_token);
                g_free (name);
        } else {
                g_error ("requested method token for %s\n", klass->name);
        }
 
+       g_hash_table_insert (assembly->vararg_aux_hash, GUINT_TO_POINTER (token), sig);
+       mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), obj);
        return token;
 }
 
@@ -4610,7 +4893,7 @@ mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, Mon
  */
 guint32
 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj, 
-                                                gboolean create_methodspec, gboolean register_token)
+                                                gboolean create_open_instance, gboolean register_token)
 {
        MonoClass *klass;
        guint32 token = 0;
@@ -4629,7 +4912,7 @@ mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj,
                if (tb->module->dynamic_image == assembly && !tb->generic_params && !mb->generic_params)
                        token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
                else
-                       token = mono_image_get_methodbuilder_token (assembly, mb, create_methodspec);
+                       token = mono_image_get_methodbuilder_token (assembly, mb, create_open_instance);
                /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
        } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
                MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
@@ -4646,31 +4929,47 @@ mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj,
                if (tb->generic_params) {
                        token = mono_image_get_generic_field_token (assembly, fb);
                } else {
-                       token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
+                       if ((tb->module->dynamic_image == assembly)) {
+                               token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
+                       } else {
+                               token = mono_image_get_fieldref_token (assembly, (MonoObject*)fb, fb->handle);
+                       }
                }
        } else if (strcmp (klass->name, "TypeBuilder") == 0) {
                MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
-               token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
+               if (create_open_instance && tb->generic_params) {
+                       MonoType *type;
+                       init_type_builder_generics (obj);
+                       type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
+                       token = mono_image_typedef_or_ref_full (assembly, type, TRUE);
+                       token = mono_metadata_token_from_dor (token);
+               } else if (tb->module->dynamic_image == assembly) {
+                       token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
+               } else {
+                       MonoType *type;
+                       type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
+                       token = mono_metadata_token_from_dor (mono_image_typedef_or_ref (assembly, type));
+               }
        } else if (strcmp (klass->name, "MonoType") == 0) {
-               MonoReflectionType *tb = (MonoReflectionType *)obj;
-               MonoClass *mc = mono_class_from_mono_type (tb->type);
+               MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
+               MonoClass *mc = mono_class_from_mono_type (type);
                token = mono_metadata_token_from_dor (
-                       mono_image_typedef_or_ref_full (assembly, tb->type, mc->generic_container == NULL));
+                       mono_image_typedef_or_ref_full (assembly, type, mc->generic_container == NULL || create_open_instance));
        } else if (strcmp (klass->name, "GenericTypeParameterBuilder") == 0) {
-               MonoReflectionType *tb = (MonoReflectionType *)obj;
+               MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
                token = mono_metadata_token_from_dor (
-                       mono_image_typedef_or_ref (assembly, tb->type));
+                       mono_image_typedef_or_ref (assembly, type));
        } else if (strcmp (klass->name, "MonoGenericClass") == 0) {
-               MonoReflectionType *tb = (MonoReflectionType *)obj;
+               MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
                token = mono_metadata_token_from_dor (
-                       mono_image_typedef_or_ref (assembly, tb->type));
+                       mono_image_typedef_or_ref (assembly, type));
        } else if (strcmp (klass->name, "MonoCMethod") == 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) {
-                       if (create_methodspec)
+                       if (create_open_instance)
                                token = mono_image_get_methodspec_token (assembly, m->method);
                        else
                                token = mono_image_get_inflated_method_token (assembly, m->method);
@@ -4693,7 +4992,7 @@ mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj,
                                token = MONO_TOKEN_METHOD_DEF | method_table_idx;
                        }
                } else {
-                       token = mono_image_get_methodref_token (assembly, m->method, create_methodspec);
+                       token = mono_image_get_methodref_token (assembly, m->method, create_open_instance);
                }
                /*g_print ("got token 0x%08x for %s\n", token, m->method->name);*/
        } else if (strcmp (klass->name, "MonoField") == 0) {
@@ -4703,7 +5002,7 @@ mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj,
                        field_table_idx --;
                        token = MONO_TOKEN_FIELD_DEF | field_table_idx;
                } else {
-                       token = mono_image_get_fieldref_token (assembly, f);
+                       token = mono_image_get_fieldref_token (assembly, (MonoObject*)f, f->field);
                }
                /*g_print ("got token 0x%08x for %s\n", token, f->field->name);*/
        } else if (strcmp (klass->name, "MonoArrayMethod") == 0) {
@@ -4713,18 +5012,22 @@ mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj,
                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;
+               MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
                token = mono_metadata_token_from_dor (
-                       mono_image_typedef_or_ref (assembly, tb->type));
+                       mono_image_typedef_or_ref (assembly, type));
        } else if (strcmp (klass->name, "FieldOnTypeBuilderInst") == 0) {
                MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
                token = mono_image_get_field_on_inst_token (assembly, f);
        } else if (strcmp (klass->name, "ConstructorOnTypeBuilderInst") == 0) {
                MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
-               token = mono_image_get_ctor_on_inst_token (assembly, c, create_methodspec);
+               token = mono_image_get_ctor_on_inst_token (assembly, c, create_open_instance);
        } else if (strcmp (klass->name, "MethodOnTypeBuilderInst") == 0) {
                MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
-               token = mono_image_get_method_on_inst_token (assembly, m, create_methodspec);
+               token = mono_image_get_method_on_inst_token (assembly, m, create_open_instance);
+       } else if (is_sre_array (klass) || is_sre_byref (klass) || is_sre_pointer (klass)) {
+               MonoReflectionType *type = (MonoReflectionType *)obj;
+               token = mono_metadata_token_from_dor (
+                               mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle (type)));
        } else {
                g_error ("requested token for %s\n", klass->name);
        }
@@ -4768,6 +5071,7 @@ create_dynamic_mono_image (MonoDynamicAssembly *assembly, char *assembly_name, c
                version = mono_get_runtime_info ()->runtime_version;
 
 #if HAVE_BOEHM_GC
+       /* The MonoGHashTable's need GC tracking */
        image = GC_MALLOC (sizeof (MonoDynamicImage));
 #else
        image = g_new0 (MonoDynamicImage, 1);
@@ -4794,7 +5098,9 @@ create_dynamic_mono_image (MonoDynamicAssembly *assembly, char *assembly_name, c
        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->vararg_aux_hash = g_hash_table_new (NULL, NULL);
        image->handleref = g_hash_table_new (NULL, NULL);
+       image->handleref_managed = mono_g_hash_table_new_type ((GHashFunc)mono_object_hash, NULL, MONO_HASH_KEY_GC);
        image->tokens = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC);
        image->generic_def_objects = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC);
        image->methodspec = mono_g_hash_table_new_type ((GHashFunc)mono_object_hash, NULL, MONO_HASH_KEY_GC);
@@ -4857,6 +5163,8 @@ mono_dynamic_image_free (MonoDynamicImage *image)
                g_hash_table_destroy (di->typeref);
        if (di->handleref)
                g_hash_table_destroy (di->handleref);
+       if (di->handleref_managed)
+               mono_g_hash_table_destroy (di->handleref_managed);
        if (di->tokens)
                mono_g_hash_table_destroy (di->tokens);
        if (di->generic_def_objects)
@@ -4877,11 +5185,7 @@ mono_dynamic_image_free (MonoDynamicImage *image)
        if (di->gen_params) {
                for (i = 0; i < di->gen_params->len; i++) {
                        GenericParamTableEntry *entry = g_ptr_array_index (di->gen_params, i);
-                       if (entry->gparam->type.type) {
-                               MonoGenericParam *param = entry->gparam->type.type->data.generic_param;
-                               g_free ((char*)mono_generic_param_info (param)->name);
-                               g_free (param);
-                       }
+                       mono_gc_deregister_root ((char*) &entry->gparam);
                        g_free (entry);
                }
                g_ptr_array_free (di->gen_params, TRUE);
@@ -4894,6 +5198,8 @@ mono_dynamic_image_free (MonoDynamicImage *image)
                g_hash_table_destroy (di->field_to_table_idx);
        if (di->method_aux_hash)
                g_hash_table_destroy (di->method_aux_hash);
+       if (di->vararg_aux_hash)
+               g_hash_table_destroy (di->vararg_aux_hash);
        g_free (di->strong_name);
        g_free (di->win32_res);
        if (di->public_key)
@@ -4934,6 +5240,7 @@ mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
                return;
 
 #if HAVE_BOEHM_GC
+       /* assembly->assembly.image might be GC allocated */
        assembly = assemblyb->dynamic_assembly = GC_MALLOC (sizeof (MonoDynamicAssembly));
 #else
        assembly = assemblyb->dynamic_assembly = g_new0 (MonoDynamicAssembly, 1);
@@ -4971,11 +5278,19 @@ mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
 
        assembly->run = assemblyb->access != 2;
        assembly->save = assemblyb->access != 1;
+       assembly->domain = domain;
 
        image = create_dynamic_mono_image (assembly, mono_string_to_utf8 (assemblyb->name), g_strdup ("RefEmit_YouForgotToDefineAModule"));
        image->initial_image = TRUE;
        assembly->assembly.aname.name = image->image.name;
        assembly->assembly.image = &image->image;
+       if (assemblyb->pktoken && assemblyb->pktoken->max_length) {
+               /* -1 to correct for the trailing NULL byte */
+               if (assemblyb->pktoken->max_length != MONO_PUBLIC_KEY_TOKEN_LENGTH - 1) {
+                       g_error ("Public key token length invalid for assembly %s: %i", assembly->assembly.aname.name, assemblyb->pktoken->max_length);
+               }
+               memcpy (&assembly->assembly.aname.public_key_token, mono_array_addr (assemblyb->pktoken, guint8, 0), assemblyb->pktoken->max_length);           
+       }
 
        mono_domain_assemblies_lock (domain);
        domain->domain_assemblies = g_slist_prepend (domain->domain_assemblies, assembly);
@@ -5495,10 +5810,7 @@ mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file)
        cli_header = (MonoCLIHeader*)(assembly->code.data + assembly->cli_header_offset);
        cli_header->ch_size = GUINT32_FROM_LE (72);
        cli_header->ch_runtime_major = GUINT16_FROM_LE (2);
-       if (mono_framework_version () > 1)
-               cli_header->ch_runtime_minor = GUINT16_FROM_LE (5);
-       else 
-               cli_header->ch_runtime_minor = GUINT16_FROM_LE (0);
+       cli_header->ch_runtime_minor = GUINT16_FROM_LE (5);
        cli_header->ch_flags = GUINT32_FROM_LE (assemblyb->pe_kind);
        if (assemblyb->entry_point) {
                guint32 table_idx = 0;
@@ -5829,16 +6141,24 @@ mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
        MonoDynamicImage *image = moduleb->dynamic_image;
        MonoReflectionAssemblyBuilder *ab = moduleb->assemblyb;
        if (!image) {
+               MonoError error;
                int module_count;
                MonoImage **new_modules;
                MonoImage *ass;
+               char *name, *fqname;
                /*
                 * FIXME: we already created an image in mono_image_basic_init (), but
                 * we don't know which module it belongs to, since that is only 
                 * determined at assembly save time.
                 */
                /*image = (MonoDynamicImage*)ab->dynamic_assembly->assembly.image; */
-               image = create_dynamic_mono_image (ab->dynamic_assembly, mono_string_to_utf8 (ab->name), mono_string_to_utf8 (moduleb->module.fqname));
+               name = mono_string_to_utf8 (ab->name);
+               fqname = mono_string_to_utf8_checked (moduleb->module.fqname, &error);
+               if (!mono_error_ok (&error)) {
+                       g_free (name);
+                       mono_error_raise_exception (&error);
+               }
+               image = create_dynamic_mono_image (ab->dynamic_assembly, name, fqname);
 
                moduleb->module.image = &image->image;
                moduleb->dynamic_image = image;
@@ -5860,6 +6180,15 @@ mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
        }
 }
 
+void
+mono_image_set_wrappers_type (MonoReflectionModuleBuilder *moduleb, MonoReflectionType *type)
+{
+       MonoDynamicImage *image = moduleb->dynamic_image;
+
+       g_assert (type->type);
+       image->wrappers_type = mono_class_from_mono_type (type->type);
+}
+
 #endif
 
 /*
@@ -5872,14 +6201,18 @@ mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
 MonoReflectionAssembly*
 mono_assembly_get_object (MonoDomain *domain, MonoAssembly *assembly)
 {
-       static MonoClass *System_Reflection_Assembly;
+       static MonoClass *assembly_type;
        MonoReflectionAssembly *res;
        
        CHECK_OBJECT (MonoReflectionAssembly *, assembly, NULL);
-       if (!System_Reflection_Assembly)
-               System_Reflection_Assembly = mono_class_from_name (
-                       mono_defaults.corlib, "System.Reflection", "Assembly");
-       res = (MonoReflectionAssembly *)mono_object_new (domain, System_Reflection_Assembly);
+       if (!assembly_type) {
+               MonoClass *class = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoAssembly");
+               if (class == NULL)
+                       class = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Assembly");
+               g_assert (class);
+               assembly_type = class;
+       }
+       res = (MonoReflectionAssembly *)mono_object_new (domain, assembly_type);
        res->assembly = assembly;
 
        CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
@@ -5890,15 +6223,19 @@ mono_assembly_get_object (MonoDomain *domain, MonoAssembly *assembly)
 MonoReflectionModule*   
 mono_module_get_object   (MonoDomain *domain, MonoImage *image)
 {
-       static MonoClass *System_Reflection_Module;
+       static MonoClass *module_type;
        MonoReflectionModule *res;
        char* basename;
        
        CHECK_OBJECT (MonoReflectionModule *, image, NULL);
-       if (!System_Reflection_Module)
-               System_Reflection_Module = mono_class_from_name (
-                       mono_defaults.corlib, "System.Reflection", "Module");
-       res = (MonoReflectionModule *)mono_object_new (domain, System_Reflection_Module);
+       if (!module_type) {
+               MonoClass *class = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoModule");
+               if (class == NULL)
+                       class = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Module");
+               g_assert (class);
+               module_type = class;
+       }
+       res = (MonoReflectionModule *)mono_object_new (domain, module_type);
 
        res->image = image;
        MONO_OBJECT_SETREF (res, assembly, (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly));
@@ -5930,7 +6267,7 @@ mono_module_get_object   (MonoDomain *domain, MonoImage *image)
 MonoReflectionModule*   
 mono_module_file_get_object (MonoDomain *domain, MonoImage *image, int table_index)
 {
-       static MonoClass *System_Reflection_Module;
+       static MonoClass *module_type;
        MonoReflectionModule *res;
        MonoTableInfo *table;
        guint32 cols [MONO_FILE_SIZE];
@@ -5938,10 +6275,14 @@ mono_module_file_get_object (MonoDomain *domain, MonoImage *image, int table_ind
        guint32 i, name_idx;
        const char *val;
        
-       if (!System_Reflection_Module)
-               System_Reflection_Module = mono_class_from_name (
-                       mono_defaults.corlib, "System.Reflection", "Module");
-       res = (MonoReflectionModule *)mono_object_new (domain, System_Reflection_Module);
+       if (!module_type) {
+               MonoClass *class = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoModule");
+               if (class == NULL)
+                       class = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Module");
+               g_assert (class);
+               module_type = class;
+       }
+       res = (MonoReflectionModule *)mono_object_new (domain, module_type);
 
        table = &image->tables [MONO_TABLE_FILE];
        g_assert (table_index < table->rows);
@@ -5969,133 +6310,6 @@ mono_module_file_get_object (MonoDomain *domain, MonoImage *image, int table_ind
        return res;
 }
 
-static gboolean
-mymono_metadata_type_equal (MonoType *t1, MonoType *t2)
-{
-       if ((t1->type != t2->type) ||
-           (t1->byref != t2->byref))
-               return FALSE;
-
-       switch (t1->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_STRING:
-       case MONO_TYPE_I:
-       case MONO_TYPE_U:
-       case MONO_TYPE_OBJECT:
-       case MONO_TYPE_TYPEDBYREF:
-               return TRUE;
-       case MONO_TYPE_VALUETYPE:
-       case MONO_TYPE_CLASS:
-       case MONO_TYPE_SZARRAY:
-               return t1->data.klass == t2->data.klass;
-       case MONO_TYPE_PTR:
-               return mymono_metadata_type_equal (t1->data.type, t2->data.type);
-       case MONO_TYPE_ARRAY:
-               if (t1->data.array->rank != t2->data.array->rank)
-                       return FALSE;
-               return t1->data.array->eklass == t2->data.array->eklass;
-       case MONO_TYPE_GENERICINST: {
-               int i;
-               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;
-               /* 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;
-       }
-       case MONO_TYPE_VAR:
-       case MONO_TYPE_MVAR:
-               return t1->data.generic_param == t2->data.generic_param;
-       default:
-               g_error ("implement type compare for %0x!", t1->type);
-               return FALSE;
-       }
-
-       return FALSE;
-}
-
-static guint
-mymono_metadata_type_hash (MonoType *t1)
-{
-       guint hash;
-
-       hash = t1->type;
-
-       hash |= t1->byref << 6; /* do not collide with t1->type values */
-       switch (t1->type) {
-       case MONO_TYPE_VALUETYPE:
-       case MONO_TYPE_CLASS:
-       case MONO_TYPE_SZARRAY:
-               /* check if the distribution is good enough */
-               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;
-}
-
-static MonoReflectionGenericClass*
-mono_generic_class_get_object (MonoDomain *domain, MonoType *geninst)
-{
-       static MonoClass *System_Reflection_MonoGenericClass;
-       MonoReflectionGenericClass *res;
-       MonoClass *klass, *gklass;
-
-       if (!System_Reflection_MonoGenericClass) {
-               System_Reflection_MonoGenericClass = mono_class_from_name (
-                       mono_defaults.corlib, "System.Reflection", "MonoGenericClass");
-               g_assert (System_Reflection_MonoGenericClass);
-       }
-
-       klass = mono_class_from_mono_type (geninst);
-       gklass = klass->generic_class->container_class;
-
-       mono_class_init (klass);
-
-#ifdef HAVE_SGEN_GC
-       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;
-       g_assert (gklass->reflection_info);
-       g_assert (!strcmp (((MonoObject*)gklass->reflection_info)->vtable->klass->name, "TypeBuilder"));
-       MONO_OBJECT_SETREF (res, generic_type, gklass->reflection_info);
-
-       return res;
-}
-
 static gboolean
 verify_safe_for_managed_space (MonoType *type)
 {
@@ -6125,6 +6339,49 @@ verify_safe_for_managed_space (MonoType *type)
        return TRUE;
 }
 
+static MonoType*
+mono_type_normalize (MonoType *type)
+{
+       int i;
+       MonoGenericClass *gclass;
+       MonoGenericInst *ginst;
+       MonoClass *gtd;
+       MonoGenericContainer *gcontainer;
+       MonoType **argv = NULL;
+       gboolean is_denorm_gtd = TRUE, requires_rebind = FALSE;
+
+       if (type->type != MONO_TYPE_GENERICINST)
+               return type;
+
+       gclass = type->data.generic_class;
+       ginst = gclass->context.class_inst;
+       if (!ginst->is_open)
+               return type;
+
+       gtd = gclass->container_class;
+       gcontainer = gtd->generic_container;
+       argv = g_newa (MonoType*, ginst->type_argc);
+
+       for (i = 0; i < ginst->type_argc; ++i) {
+               MonoType *t = ginst->type_argv [i], *norm;
+               if (t->type != MONO_TYPE_VAR || t->data.generic_param->num != i || t->data.generic_param->owner != gcontainer)
+                       is_denorm_gtd = FALSE;
+               norm = mono_type_normalize (t);
+               argv [i] = norm;
+               if (norm != t)
+                       requires_rebind = TRUE;
+       }
+
+       if (is_denorm_gtd)
+               return type->byref == gtd->byval_arg.byref ? &gtd->byval_arg : &gtd->this_arg;
+
+       if (requires_rebind) {
+               MonoClass *klass = mono_class_bind_generic_parameters (gtd, ginst->type_argc, argv, gclass->is_dynamic);
+               return type->byref == klass->byval_arg.byref ? &klass->byval_arg : &klass->this_arg;
+       }
+
+       return type;
+}
 /*
  * mono_type_get_object:
  * @domain: an app domain
@@ -6135,6 +6392,7 @@ verify_safe_for_managed_space (MonoType *type)
 MonoReflectionType*
 mono_type_get_object (MonoDomain *domain, MonoType *type)
 {
+       MonoType *norm_type;
        MonoReflectionType *res;
        MonoClass *klass = mono_class_from_mono_type (type);
 
@@ -6154,7 +6412,7 @@ mono_type_get_object (MonoDomain *domain, MonoType *type)
         * the MonoType from there and avoid all locking and hash table lookups.
         * 
         * We cannot do this for TypeBuilders as mono_reflection_create_runtime_class expects
-        * that the resulting object is diferent.   
+        * that the resulting object is different.   
         */
        if (type == &klass->byval_arg && !klass->image->dynamic) {
                MonoVTable *vtable = mono_class_try_get_vtable (domain, klass);
@@ -6165,49 +6423,75 @@ mono_type_get_object (MonoDomain *domain, MonoType *type)
        mono_loader_lock (); /*FIXME mono_class_init and mono_class_vtable acquire it*/
        mono_domain_lock (domain);
        if (!domain->type_hash)
-               domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mymono_metadata_type_hash, 
-                               (GCompareFunc)mymono_metadata_type_equal, MONO_HASH_VALUE_GC);
+               domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mono_metadata_type_hash, 
+                               (GCompareFunc)mono_metadata_type_equal, MONO_HASH_VALUE_GC);
        if ((res = mono_g_hash_table_lookup (domain->type_hash, type))) {
                mono_domain_unlock (domain);
                mono_loader_unlock ();
                return res;
        }
-       /* Create a MonoGenericClass object for instantiations of not finished TypeBuilders */
-       if ((type->type == MONO_TYPE_GENERICINST) && type->data.generic_class->is_dynamic && !type->data.generic_class->container_class->wastypebuilder) {
-               res = (MonoReflectionType *)mono_generic_class_get_object (domain, type);
+
+       /*Types must be normalized so a generic instance of the GTD get's the same inner type.
+        * For example in: Foo<A,B>; Bar<A> : Foo<A, Bar<A>>
+        * The second Bar will be encoded a generic instance of Bar with <A> as parameter.
+        * On all other places, Bar<A> will be encoded as the GTD itself. This is an implementation
+        * artifact of how generics are encoded and should be transparent to managed code so we
+        * need to weed out this diference when retrieving managed System.Type objects.
+        */
+       norm_type = mono_type_normalize (type);
+       if (norm_type != type) {
+               res = mono_type_get_object (domain, norm_type);
                mono_g_hash_table_insert (domain->type_hash, type, res);
                mono_domain_unlock (domain);
                mono_loader_unlock ();
                return res;
        }
 
+       /* This MonoGenericClass hack is no longer necessary. Let's leave it here until we finish with the 2-stage type-builder setup.*/
+       if ((type->type == MONO_TYPE_GENERICINST) && type->data.generic_class->is_dynamic && !type->data.generic_class->container_class->wastypebuilder)
+               g_assert (0);
+
        if (!verify_safe_for_managed_space (type)) {
                mono_domain_unlock (domain);
                mono_loader_unlock ();
                mono_raise_exception (mono_get_exception_invalid_operation ("This type cannot be propagated to managed space"));
        }
 
-       if (klass->reflection_info && !klass->wastypebuilder) {
+       if (mono_class_get_ref_info (klass) && !klass->wastypebuilder) {
+               gboolean is_type_done = TRUE;
+               /* Generic parameters have reflection_info set but they are not finished together with their enclosing type.
+                * We must ensure that once a type is finished we don't return a GenericTypeParameterBuilder.
+                * We can't simply close the types as this will interfere with other parts of the generics machinery.
+               */
+               if (klass->byval_arg.type == MONO_TYPE_MVAR || klass->byval_arg.type == MONO_TYPE_VAR) {
+                       MonoGenericParam *gparam = klass->byval_arg.data.generic_param;
+
+                       if (gparam->owner && gparam->owner->is_method) {
+                               MonoMethod *method = gparam->owner->owner.method;
+                               if (method && mono_class_get_generic_type_definition (method->klass)->wastypebuilder)
+                                       is_type_done = FALSE;
+                       } else if (gparam->owner && !gparam->owner->is_method) {
+                               MonoClass *klass = gparam->owner->owner.klass;
+                               if (klass && mono_class_get_generic_type_definition (klass)->wastypebuilder)
+                                       is_type_done = FALSE;
+                       }
+               } 
+
                /* g_assert_not_reached (); */
                /* should this be considered an error condition? */
-               if (!type->byref) {
+               if (is_type_done && !type->byref) {
                        mono_domain_unlock (domain);
                        mono_loader_unlock ();
-                       return klass->reflection_info;
+                       return mono_class_get_ref_info (klass);
                }
        }
-       // FIXME: Get rid of this, do it in the icalls for 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
+       /* This is stored in vtables/JITted code so it has to be pinned */
+       res = (MonoReflectionType *)mono_object_new_pinned (domain, mono_defaults.monotype_class);
        res->type = type;
        mono_g_hash_table_insert (domain->type_hash, type, res);
 
        if (type->type == MONO_TYPE_VOID)
-               MONO_OBJECT_SETREF (domain, typeof_void, res);
+               domain->typeof_void = (MonoObject*)res;
 
        mono_domain_unlock (domain);
        mono_loader_unlock ();
@@ -6324,11 +6608,15 @@ mono_field_get_object (MonoDomain *domain, MonoClass *klass, MonoClassField *fie
        res->klass = klass;
        res->field = field;
        MONO_OBJECT_SETREF (res, name, mono_string_new (domain, mono_field_get_name (field)));
-       if (is_field_on_inst (field))
+
+       if (is_field_on_inst (field)) {
                res->attrs = get_field_on_inst_generic_type (field)->attrs;
-       else
-               res->attrs = field->type->attrs;
-       MONO_OBJECT_SETREF (res, type, mono_type_get_object (domain, field->type));
+               MONO_OBJECT_SETREF (res, type, mono_type_get_object (domain, field->type));
+       } else {
+               if (field->type)
+                       MONO_OBJECT_SETREF (res, type, mono_type_get_object (domain, field->type));
+               res->attrs = mono_field_get_flags (field);
+       }
        CACHE_OBJECT (MonoReflectionField *, field, res, klass);
 }
 
@@ -6439,6 +6727,7 @@ mono_param_get_objects_internal (MonoDomain *domain, MonoMethod *method, MonoCla
 {
        static MonoClass *System_Reflection_ParameterInfo;
        static MonoClass *System_Reflection_ParameterInfo_array;
+       MonoError error;
        MonoArray *res = NULL;
        MonoReflectionMethod *member = NULL;
        MonoReflectionParameter *param = NULL;
@@ -6463,8 +6752,12 @@ mono_param_get_objects_internal (MonoDomain *domain, MonoMethod *method, MonoCla
                mono_memory_barrier ();
                System_Reflection_ParameterInfo_array = klass;
        }
-       
-       if (!mono_method_signature (method)->param_count)
+
+       sig = mono_method_signature_checked (method, &error);
+       if (!mono_error_ok (&error))
+               mono_error_raise_exception (&error);
+
+       if (!sig->param_count)
                return mono_array_new_specific (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), 0);
 
        /* Note: the cache is based on the address of the signature into the method
@@ -6472,7 +6765,6 @@ mono_param_get_objects_internal (MonoDomain *domain, MonoMethod *method, MonoCla
         */
        CHECK_OBJECT (MonoArray*, &(method->signature), refclass);
 
-       sig = mono_method_signature (method);
        member = mono_method_get_object (domain, method, refclass);
        names = g_new (char *, sig->param_count);
        mono_method_get_param_names (method, (const char **) names);
@@ -6568,13 +6860,17 @@ mono_method_body_get_object (MonoDomain *domain, MonoMethod *method)
        static MonoClass *System_Reflection_LocalVariableInfo = NULL;
        static MonoClass *System_Reflection_ExceptionHandlingClause = NULL;
        MonoReflectionMethodBody *ret;
-       MonoMethodNormal *mn;
        MonoMethodHeader *header;
+       MonoImage *image;
        guint32 method_rva, local_var_sig_token;
     char *ptr;
        unsigned char format, flags;
        int i;
 
+       /* for compatibility with .net */
+    if (method->dynamic)
+        mono_raise_exception (mono_get_exception_invalid_operation (NULL));
+
        if (!System_Reflection_MethodBody)
                System_Reflection_MethodBody = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MethodBody");
        if (!System_Reflection_LocalVariableInfo)
@@ -6589,28 +6885,31 @@ mono_method_body_get_object (MonoDomain *domain, MonoMethod *method)
            (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
            (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME))
                return NULL;
-       mn = (MonoMethodNormal *)method;
+
+       image = method->klass->image;
        header = mono_method_get_header (method);
-       
-       /* Obtain local vars signature token */
-       method_rva = mono_metadata_decode_row_col (&method->klass->image->tables [MONO_TABLE_METHOD], mono_metadata_token_index (method->token) - 1, MONO_METHOD_RVA);
-       ptr = mono_image_rva_map (method->klass->image, method_rva);
-       flags = *(const unsigned char *) ptr;
-       format = flags & METHOD_HEADER_FORMAT_MASK;
-       switch (format){
-       case METHOD_HEADER_TINY_FORMAT:
-       case METHOD_HEADER_TINY_FORMAT1:
-               local_var_sig_token = 0;
-               break;
-       case METHOD_HEADER_FAT_FORMAT:
-               ptr += 2;
-               ptr += 2;
-               ptr += 4;
-               local_var_sig_token = read32 (ptr);
-               break;
-       default:
-               g_assert_not_reached ();
-       }
+
+       if (!image->dynamic) {
+               /* Obtain local vars signature token */
+               method_rva = mono_metadata_decode_row_col (&image->tables [MONO_TABLE_METHOD], mono_metadata_token_index (method->token) - 1, MONO_METHOD_RVA);
+               ptr = mono_image_rva_map (image, method_rva);
+               flags = *(const unsigned char *) ptr;
+               format = flags & METHOD_HEADER_FORMAT_MASK;
+               switch (format){
+               case METHOD_HEADER_TINY_FORMAT:
+                       local_var_sig_token = 0;
+                       break;
+               case METHOD_HEADER_FAT_FORMAT:
+                       ptr += 2;
+                       ptr += 2;
+                       ptr += 4;
+                       local_var_sig_token = read32 (ptr);
+                       break;
+               default:
+                       g_assert_not_reached ();
+               }
+       } else
+               local_var_sig_token = 0; //FIXME
 
        ret = (MonoReflectionMethodBody*)mono_object_new (domain, System_Reflection_MethodBody);
 
@@ -6649,6 +6948,7 @@ mono_method_body_get_object (MonoDomain *domain, MonoMethod *method)
                mono_array_setref (ret->clauses, i, info);
        }
 
+       mono_metadata_free_mh (header);
        CACHE_OBJECT (MonoReflectionMethodBody *, method, ret, NULL);
        return ret;
 }
@@ -6730,7 +7030,7 @@ get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types)
                mono_metadata_decode_row (paramt, i - 1, param_cols, MONO_PARAM_SIZE);
                paramseq = param_cols [MONO_PARAM_SEQUENCE];
 
-               if (!param_cols [MONO_PARAM_FLAGS] & PARAM_ATTRIBUTE_HAS_DEFAULT) 
+               if (!(param_cols [MONO_PARAM_FLAGS] & PARAM_ATTRIBUTE_HAS_DEFAULT))
                        continue;
 
                crow = mono_metadata_get_constant_index (image, MONO_TOKEN_PARAM_DEF | i, crow + 1);
@@ -6746,7 +7046,7 @@ get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types)
        return;
 }
 
-static MonoObject *
+MonoObject *
 mono_get_object_from_blob (MonoDomain *domain, MonoType *type, const char *blob)
 {
        void *retval;
@@ -6777,23 +7077,35 @@ static int
 assembly_name_to_aname (MonoAssemblyName *assembly, char *p) {
        int found_sep;
        char *s;
+       gboolean quoted = FALSE;
 
        memset (assembly, 0, sizeof (MonoAssemblyName));
-       assembly->name = p;
        assembly->culture = "";
        memset (assembly->public_key_token, 0, MONO_PUBLIC_KEY_TOKEN_LENGTH);
 
-       while (*p && (isalnum (*p) || *p == '.' || *p == '-' || *p == '_' || *p == '$' || *p == '@'))
+       if (*p == '"') {
+               quoted = TRUE;
+               p++;
+       }
+       assembly->name = p;
+       while (*p && (isalnum (*p) || *p == '.' || *p == '-' || *p == '_' || *p == '$' || *p == '@' || g_ascii_isspace (*p)))
+               p++;
+       if (quoted) {
+               if (*p != '"')
+                       return 1;
+               *p = 0;
                p++;
-       found_sep = 0;
-       while (g_ascii_isspace (*p) || *p == ',') {
-               *p++ = 0;
-               found_sep = 1;
-               continue;
-       }
-       /* failed */
-       if (!found_sep)
+       }
+       if (*p != ',')
                return 1;
+       *p = 0;
+       /* Remove trailing whitespace */
+       s = p - 1;
+       while (*s && g_ascii_isspace (*s))
+               *s-- = 0;
+       p ++;
+       while (g_ascii_isspace (*p))
+               p++;
        while (*p) {
                if (*p == 'V' && g_ascii_strncasecmp (p, "Version=", 8) == 0) {
                        p += 8;
@@ -6981,7 +7293,8 @@ _mono_reflection_parse_type (char *name, char **endptr, gboolean is_recursed,
                                        if (!_mono_reflection_parse_type (p, &p, TRUE, subinfo))
                                                return 0;
 
-                                       if (fqname) {
+                                       /*MS is lenient on [] delimited parameters that aren't fqn - and F# uses them.*/
+                                       if (fqname && (*p != ']')) {
                                                char *aname;
 
                                                if (*p != ',')
@@ -7006,6 +7319,8 @@ _mono_reflection_parse_type (char *name, char **endptr, gboolean is_recursed,
                                                if (!*aname ||
                                                    !assembly_name_to_aname (&subinfo->assembly, aname))
                                                        return 0;
+                                       } else if (fqname && (*p == ']')) {
+                                               *p++ = 0;
                                        }
 
                                        if (i + 1 < arity) {
@@ -7141,7 +7456,7 @@ mono_reflection_get_type_internal (MonoImage *rootimage, MonoImage* image, MonoT
 
                while ((klass = mono_class_get_nested_types (parent, &iter))) {
                        if (ignorecase) {
-                               if (g_strcasecmp (klass->name, mod->data) == 0)
+                               if (mono_utf8_strcasecmp (klass->name, mod->data) == 0)
                                        break;
                        } else {
                                if (strcmp (klass->name, mod->data) == 0)
@@ -7153,7 +7468,6 @@ mono_reflection_get_type_internal (MonoImage *rootimage, MonoImage* image, MonoT
        }
        if (!klass)
                return NULL;
-       mono_class_init (klass);
 
        if (info->type_arguments) {
                MonoType **type_args = g_new0 (MonoType *, info->type_arguments->len);
@@ -7194,7 +7508,6 @@ mono_reflection_get_type_internal (MonoImage *rootimage, MonoImage* image, MonoT
                } else { /* array rank */
                        klass = mono_bounded_array_class_get (klass, modval, bounded);
                }
-               mono_class_init (klass);
        }
 
        return &klass->byval_arg;
@@ -7219,11 +7532,12 @@ mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ig
 static MonoType*
 mono_reflection_get_type_internal_dynamic (MonoImage *rootimage, MonoAssembly *assembly, MonoTypeNameParse *info, gboolean ignorecase)
 {
-       MonoReflectionAssemblyBuilder *abuilder = (MonoReflectionAssemblyBuilder*)mono_assembly_get_object (mono_domain_get (), assembly);
+       MonoReflectionAssemblyBuilder *abuilder;
        MonoType *type;
        int i;
 
        g_assert (assembly->dynamic);
+       abuilder = (MonoReflectionAssemblyBuilder*)mono_assembly_get_object (((MonoDynamicAssembly*)assembly)->domain, assembly);
 
        /* Enumerate all modules */
 
@@ -7278,7 +7592,7 @@ mono_reflection_get_type_with_rootimage (MonoImage *rootimage, MonoImage* image,
        if (info->name_space && (info->name_space [0] != '\0'))
                g_string_printf (fullName, "%s.%s", info->name_space, info->name);
        else
-               g_string_printf (fullName, info->name);
+               g_string_printf (fullName, "%s", info->name);
        for (mod = info->nested; mod; mod = mod->next)
                g_string_append_printf (fullName, "+%s", (char*)mod->data);
 
@@ -7370,14 +7684,17 @@ mono_reflection_get_token (MonoObject *obj)
        } else if (strcmp (klass->name, "FieldBuilder") == 0) {
                MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
 
-               /* Call mono_image_create_token so the object gets added to the tokens hash table */
-               token = mono_image_create_token (((MonoReflectionTypeBuilder*)fb->typeb)->module->dynamic_image, obj, FALSE, TRUE);
+               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;
        } else if (strcmp (klass->name, "MonoType") == 0) {
-               MonoReflectionType *tb = (MonoReflectionType *)obj;
-               token = mono_class_from_mono_type (tb->type)->type_token;
+               MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
+               MonoClass *mc = mono_class_from_mono_type (type);
+               if (!mono_class_init (mc))
+                       mono_raise_exception (mono_class_get_exception_for_failure (mc));
+
+               token = mc->type_token;
        } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
                   strcmp (klass->name, "MonoMethod") == 0 ||
                   strcmp (klass->name, "MonoGenericMethod") == 0 ||
@@ -7412,13 +7729,15 @@ mono_reflection_get_token (MonoObject *obj)
                token = mono_class_get_event_token (p->event);
        } else if (strcmp (klass->name, "ParameterInfo") == 0) {
                MonoReflectionParameter *p = (MonoReflectionParameter*)obj;
+               MonoClass *member_class = mono_object_class (p->MemberImpl);
+               g_assert (mono_class_is_reflection_method_or_constructor (member_class));
 
                token = mono_method_get_param_token (((MonoReflectionMethod*)p->MemberImpl)->method, p->PositionImpl);
-       } else if (strcmp (klass->name, "Module") == 0) {
+       } else if (strcmp (klass->name, "Module") == 0 || strcmp (klass->name, "MonoModule") == 0) {
                MonoReflectionModule *m = (MonoReflectionModule*)obj;
 
                token = m->token;
-       } else if (strcmp (klass->name, "Assembly") == 0) {
+       } else if (strcmp (klass->name, "Assembly") == 0 || strcmp (klass->name, "MonoAssembly") == 0) {
                token = mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1);
        } else {
                gchar *msg = g_strdup_printf ("MetadataToken is not supported for type '%s.%s'", klass->name_space, klass->name);
@@ -7488,9 +7807,18 @@ handle_enum:
                        type = mono_class_enum_basetype (t->data.klass)->type;
                        goto handle_enum;
                } else {
-                       g_error ("generic valutype %s not handled in custom attr value decoding", t->data.klass->name);
+                       MonoClass *k =  t->data.klass;
+                       
+                       if (mono_is_corlib_image (k->image) && strcmp (k->name_space, "System") == 0 && strcmp (k->name, "DateTime") == 0){
+                               guint64 *val = g_malloc (sizeof (guint64));
+                               *val = read64 (p);
+                               *end = p + 8;
+                               return val;
+                       }
                }
+               g_error ("generic valutype %s not handled in custom attr value decoding", t->data.klass->name);
                break;
+               
        case MONO_TYPE_STRING:
                if (*p == (char)0xFF) {
                        *end = p + 1;
@@ -7536,12 +7864,16 @@ handle_type:
                        int etype = *p;
                        p ++;
 
-                       if (etype == 0x51)
-                               /* See Partition II, Appendix B3 */
-                               etype = MONO_TYPE_OBJECT;
                        type = MONO_TYPE_SZARRAY;
-                       simple_type.type = etype;
-                       tklass = mono_class_from_mono_type (&simple_type);
+                       if (etype == 0x50) {
+                               tklass = mono_defaults.systemtype_class;
+                       } else {
+                               if (etype == 0x51)
+                                       /* See Partition II, Appendix B3 */
+                                       etype = MONO_TYPE_OBJECT;
+                               simple_type.type = etype;
+                               tklass = mono_class_from_mono_type (&simple_type);
+                       }
                        goto handle_enum;
                } else if (subt == 0x55) {
                        char *n;
@@ -7564,6 +7896,7 @@ handle_type:
                }
                val = load_cattr_value (image, &subc->byval_arg, p, end);
                obj = mono_object_new (mono_domain_get (), subc);
+               g_assert (!subc->has_references);
                memcpy ((char*)obj + sizeof (MonoObject), val, mono_class_value_size (subc, NULL));
                g_free (val);
                return obj;
@@ -7766,7 +8099,7 @@ find_event_index (MonoClass *klass, MonoEvent *event) {
 }
 
 static MonoObject*
-create_custom_attr (MonoImage *image, MonoMethod *method, const guchar *data, guint32 len)
+create_custom_attr (MonoImage *image, MonoMethod *method, const guchar *data, guint32 len, MonoError *error)
 {
        const char *p = (const char*)data;
        const char *named;
@@ -7776,8 +8109,15 @@ create_custom_attr (MonoImage *image, MonoMethod *method, const guchar *data, gu
        void **params;
        MonoMethodSignature *sig;
 
+       mono_error_init (error);
+
        mono_class_init (method->klass);
 
+       if (!mono_verifier_verify_cattr_content (image, method, data, len, NULL)) {
+               mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
+               return NULL;
+       }
+
        if (len == 0) {
                attr = mono_object_new (mono_domain_get (), method->klass);
                mono_runtime_invoke (method, attr, NULL, NULL);
@@ -7859,51 +8199,51 @@ create_custom_attr (MonoImage *image, MonoMethod *method, const guchar *data, gu
 
        return attr;
 }
-
-static MonoObject*
-create_custom_attr_data (MonoImage *image, MonoMethod *method, const guchar *data, guint32 len)
+       
+/*
+ * mono_reflection_create_custom_attr_data_args:
+ *
+ *   Create an array of typed and named arguments from the cattr blob given by DATA.
+ * TYPED_ARGS and NAMED_ARGS will contain the objects representing the arguments,
+ * NAMED_ARG_INFO will contain information about the named arguments.
+ */
+void
+mono_reflection_create_custom_attr_data_args (MonoImage *image, MonoMethod *method, const guchar *data, guint32 len, MonoArray **typed_args, MonoArray **named_args, CattrNamedArg **named_arg_info)
 {
        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];
+       CattrNamedArg *arginfo = NULL;
 
-       mono_class_init (method->klass);
+       if (!mono_verifier_verify_cattr_content (image, method, data, len, NULL))
+               return;
 
-       if (!ctor)
-               ctor = mono_class_get_method_from_name (mono_defaults.customattribute_data_class, ".ctor", 3);
+       mono_class_init (method->klass);
 
+       *typed_args = NULL;
+       *named_args = NULL;
+       *named_arg_info = NULL;
+       
        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;
+               return;
 
        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;
+               MonoObject *obj;
                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);
+               mono_array_setref (typedargs, i, obj);
 
                if (!type_is_reference (mono_method_signature (method)->params [i]))
                        g_free (val);
@@ -7914,6 +8254,10 @@ create_custom_attr_data (MonoImage *image, MonoMethod *method, const guchar *dat
        namedargs = mono_array_new (domain, mono_get_object_class (), num_named);
        named += 2;
        attrklass = method->klass;
+
+       arginfo = g_new0 (CattrNamedArg, num_named);
+       *named_arg_info = arginfo;
+
        for (j = 0; j < num_named; j++) {
                gint name_len;
                char *name, named_type, data_type;
@@ -7938,88 +8282,164 @@ create_custom_attr_data (MonoImage *image, MonoMethod *method, const guchar *dat
                name [name_len] = 0;
                named += name_len;
                if (named_type == 0x53) {
-                       MonoObject *obj, *typedarg, *namedarg;
+                       MonoObject *obj;
                        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);
+                       void *val;
+
+                       arginfo [j].type = field->type;
+                       arginfo [j].field = field;
+
+                       val = load_cattr_value (image, field->type, named, &named);
                        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);
+                       mono_array_setref (namedargs, j, obj);
                        if (!type_is_reference (field->type))
                                g_free (val);
                } else if (named_type == 0x54) {
-                       MonoObject *obj, *typedarg, *namedarg;
+                       MonoObject *obj;
                        MonoType *prop_type;
-                       void *val, *minfo;
                        MonoProperty *prop = mono_class_get_property_from_name (attrklass, name);
+                       void *val;
 
                        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);
+
+                       arginfo [j].type = prop_type;
+                       arginfo [j].prop = 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);
+                       mono_array_setref (namedargs, j, obj);
                        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;
+
+       *typed_args = typedargs;
+       *named_args = namedargs;
 }
 
-MonoArray*
-mono_custom_attrs_construct (MonoCustomAttrInfo *cinfo)
+void
+mono_reflection_resolve_custom_attribute_data (MonoReflectionMethod *ref_method, MonoReflectionAssembly *assembly, gpointer data, guint32 len, MonoArray **ctor_args, MonoArray **named_args)
 {
-       MonoArray *result;
-       MonoObject *attr;
+       MonoDomain *domain;
+       MonoArray *typedargs, *namedargs;
+       MonoImage *image;
+       MonoMethod *method;
+       CattrNamedArg *arginfo;
        int i;
 
-       result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, cinfo->num_attrs);
-       for (i = 0; i < cinfo->num_attrs; ++i) {
-               if (!cinfo->attrs [i].ctor)
-                       /* The cattr type is not finished yet */
-                       /* We should include the type name but cinfo doesn't contain it */
-                       mono_raise_exception (mono_get_exception_type_load (NULL, NULL));
-               attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
-               mono_array_setref (result, i, attr);
+       *ctor_args = NULL;
+       *named_args = NULL;
+
+       if (len == 0)
+               return;
+
+       image = assembly->assembly->image;
+       method = ref_method->method;
+       domain = mono_object_domain (ref_method);
+
+       if (!mono_class_init (method->klass))
+               mono_raise_exception (mono_class_get_exception_for_failure (method->klass));
+
+       mono_reflection_create_custom_attr_data_args (image, method, data, len, &typedargs, &namedargs, &arginfo);
+       if (mono_loader_get_last_error ())
+               mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
+
+       if (!typedargs || !namedargs)
+               return;
+
+       for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
+               MonoObject *obj = mono_array_get (typedargs, MonoObject*, i);
+               MonoObject *typedarg;
+
+               typedarg = create_cattr_typed_arg (mono_method_signature (method)->params [i], obj);
+               mono_array_setref (typedargs, i, typedarg);
        }
-       return result;
+
+       for (i = 0; i < mono_array_length (namedargs); ++i) {
+               MonoObject *obj = mono_array_get (namedargs, MonoObject*, i);
+               MonoObject *typedarg, *namedarg, *minfo;
+
+               if (arginfo [i].prop)
+                       minfo = (MonoObject*)mono_property_get_object (domain, NULL, arginfo [i].prop);
+               else
+                       minfo = (MonoObject*)mono_field_get_object (domain, NULL, arginfo [i].field);
+
+               typedarg = create_cattr_typed_arg (arginfo [i].type, obj);
+               namedarg = create_cattr_named_arg (minfo, typedarg);
+
+               mono_array_setref (namedargs, i, namedarg);
+       }
+
+       *ctor_args = typedargs;
+       *named_args = namedargs;
+}
+
+static MonoObject*
+create_custom_attr_data (MonoImage *image, MonoCustomAttrEntry *cattr)
+{
+       static MonoMethod *ctor;
+       MonoDomain *domain;
+       MonoObject *attr;
+       void *params [4];
+
+       g_assert (image->assembly);
+
+       if (!ctor)
+               ctor = mono_class_get_method_from_name (mono_defaults.customattribute_data_class, ".ctor", 4);
+
+       domain = mono_domain_get ();
+       attr = mono_object_new (domain, mono_defaults.customattribute_data_class);
+       params [0] = mono_method_get_object (domain, cattr->ctor, NULL);
+       params [1] = mono_assembly_get_object (domain, image->assembly);
+       params [2] = (gpointer)&cattr->data;
+       params [3] = &cattr->data_size;
+       mono_runtime_invoke (ctor, attr, params, NULL);
+       return attr;
 }
 
 static MonoArray*
-mono_custom_attrs_construct_by_type (MonoCustomAttrInfo *cinfo, MonoClass *attr_klass)
+mono_custom_attrs_construct_by_type (MonoCustomAttrInfo *cinfo, MonoClass *attr_klass, MonoError *error)
 {
        MonoArray *result;
        MonoObject *attr;
        int i, n;
 
+       mono_error_init (error);
+
        n = 0;
        for (i = 0; i < cinfo->num_attrs; ++i) {
-               if (mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass))
+               if (!attr_klass || mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass))
                        n ++;
        }
 
        result = mono_array_new_cached (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);
+               if (!cinfo->attrs [i].ctor)
+                       /* The cattr type is not finished yet */
+                       /* We should include the type name but cinfo doesn't contain it */
+                       mono_raise_exception (mono_get_exception_type_load (NULL, NULL));
+               if (!attr_klass || 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, error);
+                       if (!mono_error_ok (error))
+                               return result;
+                       mono_array_setref (result, n, attr);
                        n ++;
                }
        }
        return result;
 }
 
+MonoArray*
+mono_custom_attrs_construct (MonoCustomAttrInfo *cinfo)
+{
+       MonoError error;
+
+       return mono_custom_attrs_construct_by_type (cinfo, NULL, &error);
+}
+
 static MonoArray*
 mono_custom_attrs_data_construct (MonoCustomAttrInfo *cinfo)
 {
@@ -8029,7 +8449,7 @@ mono_custom_attrs_data_construct (MonoCustomAttrInfo *cinfo)
        
        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);
+               attr = create_custom_attr_data (cinfo->image, &cinfo->attrs [i]);
                mono_array_setref (result, i, attr);
        }
        return result;
@@ -8065,7 +8485,7 @@ mono_custom_attrs_from_index (MonoImage *image, guint32 idx)
        len = g_list_length (list);
        if (!len)
                return NULL;
-       ainfo = g_malloc0 (sizeof (MonoCustomAttrInfo) + sizeof (MonoCustomAttrEntry) * (len - MONO_ZERO_LEN_ARRAY));
+       ainfo = g_malloc0 (MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * len);
        ainfo->num_attrs = len;
        ainfo->image = image;
        for (i = 0, tmp = list; i < len; ++i, tmp = tmp->next) {
@@ -8089,6 +8509,14 @@ mono_custom_attrs_from_index (MonoImage *image, guint32 idx)
                        g_free (ainfo);
                        return NULL;
                }
+
+               if (!mono_verifier_verify_cattr_blob (image, cols [MONO_CUSTOM_ATTR_VALUE], NULL)) {
+                       /*FIXME raising an exception here doesn't make any sense*/
+                       g_warning ("Invalid custom attribute blob on image %s for index %x", image->name, idx);
+                       g_list_free (list);
+                       g_free (ainfo);
+                       return NULL;
+               }
                data = mono_metadata_blob_heap (image, cols [MONO_CUSTOM_ATTR_VALUE]);
                ainfo->attrs [i].data_size = mono_metadata_decode_value (data, &data);
                ainfo->attrs [i].data = (guchar*)data;
@@ -8246,7 +8674,9 @@ mono_custom_attrs_from_param (MonoMethod *method, guint32 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);
+               if (!ainfo)
+                       return NULL;
+               size = MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * ainfo->num_attrs;
                res = g_malloc0 (size);
                memcpy (res, ainfo, size);
                return res;
@@ -8254,6 +8684,8 @@ mono_custom_attrs_from_param (MonoMethod *method, guint32 param)
 
        image = method->klass->image;
        method_index = mono_method_get_index (method);
+       if (!method_index)
+               return NULL;
        ca = &image->tables [MONO_TABLE_METHOD];
 
        param_list = mono_metadata_decode_row_col (ca, method_index - 1, MONO_METHOD_PARAMLIST);
@@ -8335,13 +8767,14 @@ mono_reflection_get_custom_attrs_info (MonoObject *obj)
        
        klass = obj->vtable->klass;
        if (klass == mono_defaults.monotype_class) {
-               MonoReflectionType *rtype = (MonoReflectionType*)obj;
-               klass = mono_class_from_mono_type (rtype->type);
+               MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
+               klass = mono_class_from_mono_type (type);
+               /*We cannot mono_class_init the class from which we'll load the custom attributes since this must work with broken types.*/
                cinfo = mono_custom_attrs_from_class (klass);
-       } else if (strcmp ("Assembly", klass->name) == 0) {
+       } else if (strcmp ("Assembly", klass->name) == 0 || strcmp ("MonoAssembly", klass->name) == 0) {
                MonoReflectionAssembly *rassembly = (MonoReflectionAssembly*)obj;
                cinfo = mono_custom_attrs_from_assembly (rassembly->assembly);
-       } else if (strcmp ("Module", klass->name) == 0) {
+       } else if (strcmp ("Module", klass->name) == 0 || strcmp ("MonoModule", klass->name) == 0) {
                MonoReflectionModule *module = (MonoReflectionModule*)obj;
                cinfo = mono_custom_attrs_from_module (module->image);
        } else if (strcmp ("MonoProperty", klass->name) == 0) {
@@ -8361,8 +8794,44 @@ mono_reflection_get_custom_attrs_info (MonoObject *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;
-               cinfo = mono_custom_attrs_from_param (rmethod->method, param->PositionImpl + 1);
+               MonoClass *member_class = mono_object_class (param->MemberImpl);
+               if (mono_class_is_reflection_method_or_constructor (member_class)) {
+                       MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
+                       cinfo = mono_custom_attrs_from_param (rmethod->method, param->PositionImpl + 1);
+               } else if (is_sr_mono_property (member_class)) {
+                       MonoReflectionProperty *prop = (MonoReflectionProperty *)param->MemberImpl;
+                       MonoMethod *method;
+                       if (!(method = prop->property->get))
+                               method = prop->property->set;
+                       g_assert (method);
+
+                       cinfo = mono_custom_attrs_from_param (method, param->PositionImpl + 1);
+               } 
+#ifndef DISABLE_REFLECTION_EMIT
+               else if (is_sre_method_on_tb_inst (member_class)) {/*XXX This is a workaround for Compiler Context*/
+                       MonoMethod *method = mono_reflection_method_on_tb_inst_get_handle ((MonoReflectionMethodOnTypeBuilderInst*)param->MemberImpl);
+                       cinfo = mono_custom_attrs_from_param (method, param->PositionImpl + 1);
+               } else if (is_sre_ctor_on_tb_inst (member_class)) { /*XX This is a workaround for Compiler Context*/
+                       MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)param->MemberImpl;
+                       MonoMethod *method = NULL;
+                       if (is_sre_ctor_builder (mono_object_class (c->cb)))
+                               method = ((MonoReflectionCtorBuilder *)c->cb)->mhandle;
+                       else if (is_sr_mono_cmethod (mono_object_class (c->cb)))
+                               method = ((MonoReflectionMethod *)c->cb)->method;
+                       else
+                               g_error ("mono_reflection_get_custom_attrs_info:: can't handle a CTBI with base_method of type %s", mono_type_get_full_name (member_class));
+
+                       cinfo = mono_custom_attrs_from_param (method, param->PositionImpl + 1);
+               } 
+#endif
+               else {
+                       char *type_name = mono_type_get_full_name (member_class);
+                       char *msg = g_strdup_printf ("Custom attributes on a ParamInfo with member %s are not supported", type_name);
+                       MonoException *ex = mono_get_exception_not_supported  (msg);
+                       g_free (type_name);
+                       g_free (msg);
+                       mono_raise_exception (ex);
+               }
        } else if (strcmp ("AssemblyBuilder", klass->name) == 0) {
                MonoReflectionAssemblyBuilder *assemblyb = (MonoReflectionAssemblyBuilder*)obj;
                cinfo = mono_custom_attrs_from_builders (NULL, assemblyb->assembly.assembly->image, assemblyb->cattrs);
@@ -8401,17 +8870,16 @@ mono_reflection_get_custom_attrs_info (MonoObject *obj)
  * occurs.
  */
 MonoArray*
-mono_reflection_get_custom_attrs_by_type (MonoObject *obj, MonoClass *attr_klass)
+mono_reflection_get_custom_attrs_by_type (MonoObject *obj, MonoClass *attr_klass, MonoError *error)
 {
        MonoArray *result;
        MonoCustomAttrInfo *cinfo;
 
+       mono_error_init (error);
+
        cinfo = mono_reflection_get_custom_attrs_info (obj);
        if (cinfo) {
-               if (attr_klass)
-                       result = mono_custom_attrs_construct_by_type (cinfo, attr_klass);
-               else
-                       result = mono_custom_attrs_construct (cinfo);
+               result = mono_custom_attrs_construct_by_type (cinfo, attr_klass, error);
                if (!cinfo->cached)
                        mono_custom_attrs_free (cinfo);
        } else {
@@ -8434,7 +8902,9 @@ mono_reflection_get_custom_attrs_by_type (MonoObject *obj, MonoClass *attr_klass
 MonoArray*
 mono_reflection_get_custom_attrs (MonoObject *obj)
 {
-       return mono_reflection_get_custom_attrs_by_type (obj, NULL);
+       MonoError error;
+
+       return mono_reflection_get_custom_attrs_by_type (obj, NULL, &error);
 }
 
 /*
@@ -8465,27 +8935,201 @@ mono_reflection_get_custom_attrs_data (MonoObject *obj)
 static MonoReflectionType*
 mono_reflection_type_get_underlying_system_type (MonoReflectionType* t)
 {
-        MonoMethod *method_get_underlying_system_type;
+       static MonoMethod *method_get_underlying_system_type = NULL;
+       MonoMethod *usertype_method;
+
+       if (!method_get_underlying_system_type)
+               method_get_underlying_system_type = mono_class_get_method_from_name (mono_defaults.systemtype_class, "get_UnderlyingSystemType", 0);
+       usertype_method = mono_object_get_virtual_method ((MonoObject *) t, method_get_underlying_system_type);
+        return (MonoReflectionType *) mono_runtime_invoke (usertype_method, t, NULL, NULL);
+}
+
 
-        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 gboolean
+is_corlib_type (MonoClass *class)
+{
+       return class->image == mono_defaults.corlib;
 }
 
+#define check_corlib_type_cached(_class, _namespace, _name) do { \
+       static MonoClass *cached_class; \
+       if (cached_class) \
+               return cached_class == _class; \
+       if (is_corlib_type (_class) && !strcmp (_name, _class->name) && !strcmp (_namespace, _class->name_space)) { \
+               cached_class = _class; \
+               return TRUE; \
+       } \
+       return FALSE; \
+} while (0) \
+
+
 #ifndef DISABLE_REFLECTION_EMIT
-static MonoType*
-mono_reflection_type_get_handle (MonoReflectionType* t)
+static gboolean
+is_sre_array (MonoClass *class)
+{
+       check_corlib_type_cached (class, "System.Reflection.Emit", "ArrayType");
+}
+
+static gboolean
+is_sre_byref (MonoClass *class)
+{
+       check_corlib_type_cached (class, "System.Reflection.Emit", "ByRefType");
+}
+
+static gboolean
+is_sre_pointer (MonoClass *class)
+{
+       check_corlib_type_cached (class, "System.Reflection.Emit", "PointerType");
+}
+
+static gboolean
+is_sre_generic_instance (MonoClass *class)
+{
+       check_corlib_type_cached (class, "System.Reflection", "MonoGenericClass");
+}
+
+static gboolean
+is_sre_type_builder (MonoClass *class)
+{
+       check_corlib_type_cached (class, "System.Reflection.Emit", "TypeBuilder");
+}
+
+static gboolean
+is_sre_method_builder (MonoClass *class)
+{
+       check_corlib_type_cached (class, "System.Reflection.Emit", "MethodBuilder");
+}
+
+static gboolean
+is_sre_ctor_builder (MonoClass *class)
+{
+       check_corlib_type_cached (class, "System.Reflection.Emit", "ConstructorBuilder");
+}
+
+static gboolean
+is_sre_field_builder (MonoClass *class)
+{
+       check_corlib_type_cached (class, "System.Reflection.Emit", "FieldBuilder");
+}
+
+static gboolean
+is_sre_method_on_tb_inst (MonoClass *class)
+{
+       check_corlib_type_cached (class, "System.Reflection.Emit", "MethodOnTypeBuilderInst");
+}
+
+static gboolean
+is_sre_ctor_on_tb_inst (MonoClass *class)
+{
+       check_corlib_type_cached (class, "System.Reflection.Emit", "ConstructorOnTypeBuilderInst");
+}
+
+MonoType*
+mono_reflection_type_get_handle (MonoReflectionType* ref)
 {
-        if (t->type)
-            return t->type;
+       MonoClass *class;
+       if (!ref)
+               return NULL;
+       if (ref->type)
+               return ref->type;
+
+       if (is_usertype (ref)) {
+               ref = mono_reflection_type_get_underlying_system_type (ref);
+               if (ref == NULL || is_usertype (ref))
+                       return NULL;
+               if (ref->type)
+                       return ref->type;
+       }
+
+       class = mono_object_class (ref);
+
+       if (is_sre_array (class)) {
+               MonoType *res;
+               MonoReflectionArrayType *sre_array = (MonoReflectionArrayType*)ref;
+               MonoType *base = mono_reflection_type_get_handle (sre_array->element_type);
+               g_assert (base);
+               if (sre_array->rank == 0) //single dimentional array
+                       res = &mono_array_class_get (mono_class_from_mono_type (base), 1)->byval_arg;
+               else
+                       res = &mono_bounded_array_class_get (mono_class_from_mono_type (base), sre_array->rank, TRUE)->byval_arg;
+               sre_array->type.type = res;
+               return res;
+       } else if (is_sre_byref (class)) {
+               MonoType *res;
+               MonoReflectionDerivedType *sre_byref = (MonoReflectionDerivedType*)ref;
+               MonoType *base = mono_reflection_type_get_handle (sre_byref->element_type);
+               g_assert (base);
+               res = &mono_class_from_mono_type (base)->this_arg;
+               sre_byref->type.type = res;
+               return res;
+       } else if (is_sre_pointer (class)) {
+               MonoType *res;
+               MonoReflectionDerivedType *sre_pointer = (MonoReflectionDerivedType*)ref;
+               MonoType *base = mono_reflection_type_get_handle (sre_pointer->element_type);
+               g_assert (base);
+               res = &mono_ptr_class_get (base)->byval_arg;
+               sre_pointer->type.type = res;
+               return res;
+       } else if (is_sre_generic_instance (class)) {
+               MonoType *res, **types;
+               MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)ref;
+               int i, count;
+
+               count = mono_array_length (gclass->type_arguments);
+               types = g_new0 (MonoType*, count);
+               for (i = 0; i < count; ++i) {
+                       MonoReflectionType *t = mono_array_get (gclass->type_arguments, gpointer, i);
+                       types [i] = mono_reflection_type_get_handle (t);
+                       if (!types[i]) {
+                               g_free (types);
+                               return NULL;
+                       }
+               }
 
-        t = mono_reflection_type_get_underlying_system_type (t);
-        if (t)
-            return t->type;
+               res = mono_reflection_bind_generic_parameters (gclass->generic_type, count, types);
+               g_free (types);
+               g_assert (res);
+               gclass->type.type = res;
+               return res;
+       }
 
-        return NULL;
+       g_error ("Cannot handle corlib user type %s", mono_type_full_name (&mono_object_class(ref)->byval_arg));
+       return NULL;
+}
+
+
+
+void
+mono_reflection_create_unmanaged_type (MonoReflectionType *type)
+{
+       mono_reflection_type_get_handle (type);
+}
+
+void
+mono_reflection_register_with_runtime (MonoReflectionType *type)
+{
+       MonoType *res = mono_reflection_type_get_handle (type);
+       MonoDomain *domain = mono_object_domain ((MonoObject*)type);
+       MonoClass *class;
+
+       if (!res)
+               mono_raise_exception (mono_get_exception_argument (NULL, "Invalid generic instantiation, one or more arguments are not proper user types"));
+
+       class = mono_class_from_mono_type (res);
+
+       mono_loader_lock (); /*same locking as mono_type_get_object*/
+       mono_domain_lock (domain);
+
+       if (!class->image->dynamic) {
+               mono_class_setup_supertypes (class);
+       } else {
+               if (!domain->type_hash)
+                       domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mono_metadata_type_hash, 
+                                       (GCompareFunc)mono_metadata_type_equal, MONO_HASH_VALUE_GC);
+               mono_g_hash_table_insert (domain->type_hash, res, type);
+       }
+       mono_domain_unlock (domain);
+       mono_loader_unlock ();
 }
 
 /**
@@ -8498,13 +9142,11 @@ parameters_to_signature (MonoImage *image, MonoArray *parameters) {
 
        count = parameters? mono_array_length (parameters): 0;
 
-       sig = image_g_malloc0 (image, sizeof (MonoMethodSignature) + sizeof (MonoType*) * count);
+       sig = image_g_malloc0 (image, MONO_SIZEOF_METHOD_SIGNATURE + sizeof (MonoType*) * count);
        sig->param_count = count;
        sig->sentinelpos = -1; /* FIXME */
-       for (i = 0; i < count; ++i) {
-               MonoReflectionType *pt = mono_type_array_get (parameters, i);
-               sig->params [i] = mono_reflection_type_get_handle (pt);
-       }
+       for (i = 0; i < count; ++i)
+               sig->params [i] = mono_type_array_get_and_resolve (parameters, i);
        return sig;
 }
 
@@ -8530,7 +9172,7 @@ method_builder_to_signature (MonoImage *image, MonoReflectionMethodBuilder *meth
 
        sig = parameters_to_signature (image, method->parameters);
        sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
-       sig->ret = method->rtype? monotype_cast (method->rtype)->type: &mono_defaults.void_class->byval_arg;
+       sig->ret = method->rtype? mono_reflection_type_get_handle ((MonoReflectionType*)method->rtype): &mono_defaults.void_class->byval_arg;
        sig->generic_param_count = method->generic_params ? mono_array_length (method->generic_params) : 0;
        return sig;
 }
@@ -8541,7 +9183,7 @@ dynamic_method_to_signature (MonoReflectionDynamicMethod *method) {
 
        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->ret = method->rtype? mono_reflection_type_get_handle (method->rtype): &mono_defaults.void_class->byval_arg;
        sig->generic_param_count = 0;
        return sig;
 }
@@ -8553,7 +9195,7 @@ get_prop_name_and_type (MonoObject *prop, char **name, MonoType **type)
        if (strcmp (klass->name, "PropertyBuilder") == 0) {
                MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *)prop;
                *name = mono_string_to_utf8 (pb->name);
-               *type = monotype_cast (pb->type)->type;
+               *type = mono_reflection_type_get_handle ((MonoReflectionType*)pb->type);
        } else {
                MonoReflectionProperty *p = (MonoReflectionProperty *)prop;
                *name = g_strdup (p->property->name);
@@ -8571,15 +9213,105 @@ get_field_name_and_type (MonoObject *field, char **name, MonoType **type)
        if (strcmp (klass->name, "FieldBuilder") == 0) {
                MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)field;
                *name = mono_string_to_utf8 (fb->name);
-               *type = monotype_cast (fb->type)->type;
+               *type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
        } else {
                MonoReflectionField *f = (MonoReflectionField *)field;
                *name = g_strdup (mono_field_get_name (f->field));
                *type = f->field->type;
        }
 }
+
+#else /* DISABLE_REFLECTION_EMIT */
+
+void
+mono_reflection_register_with_runtime (MonoReflectionType *type)
+{
+       /* This is empty */
+}
+
+static gboolean
+is_sre_type_builder (MonoClass *class)
+{
+       return FALSE;
+}
+
+static gboolean
+is_sre_generic_instance (MonoClass *class)
+{
+       return FALSE;
+}
+
+static void
+init_type_builder_generics (MonoObject *type)
+{
+}
+
 #endif /* !DISABLE_REFLECTION_EMIT */
 
+
+static gboolean
+is_sr_mono_field (MonoClass *class)
+{
+       check_corlib_type_cached (class, "System.Reflection", "MonoField");
+}
+
+static gboolean
+is_sr_mono_property (MonoClass *class)
+{
+       check_corlib_type_cached (class, "System.Reflection", "MonoProperty");
+}
+
+static gboolean
+is_sr_mono_method (MonoClass *class)
+{
+       check_corlib_type_cached (class, "System.Reflection", "MonoMethod");
+}
+
+static gboolean
+is_sr_mono_cmethod (MonoClass *class)
+{
+       check_corlib_type_cached (class, "System.Reflection", "MonoCMethod");
+}
+
+static gboolean
+is_sr_mono_generic_method (MonoClass *class)
+{
+       check_corlib_type_cached (class, "System.Reflection", "MonoGenericMethod");
+}
+
+static gboolean
+is_sr_mono_generic_cmethod (MonoClass *class)
+{
+       check_corlib_type_cached (class, "System.Reflection", "MonoGenericCMethod");
+}
+
+gboolean
+mono_class_is_reflection_method_or_constructor (MonoClass *class)
+{
+       return is_sr_mono_method (class) || is_sr_mono_cmethod (class) || is_sr_mono_generic_method (class) || is_sr_mono_generic_cmethod (class);
+}
+
+static gboolean
+is_usertype (MonoReflectionType *ref)
+{
+       MonoClass *class = mono_object_class (ref);
+       return class->image != mono_defaults.corlib || strcmp ("TypeDelegator", class->name) == 0;
+}
+
+static MonoReflectionType*
+mono_reflection_type_resolve_user_types (MonoReflectionType *type)
+{
+       if (!type || type->type)
+               return type;
+
+       if (is_usertype (type)) {
+               type = mono_reflection_type_get_underlying_system_type (type);
+               if (is_usertype (type))
+                       mono_raise_exception (mono_get_exception_not_supported ("User defined subclasses of System.Type are not yet supported22"));
+       }
+
+       return type;
+}
 /*
  * Encode a value in a custom attribute stream of bytes.
  * The value to encode is either supplied as an object in argument val
@@ -8680,27 +9412,12 @@ handle_enum:
        case MONO_TYPE_CLASS: {
                char *str;
                guint32 slen;
-               MonoClass *k;
                if (!arg) {
                        *p++ = 0xFF;
                        break;
                }
-               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"))) {
-                        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);
+               str = type_get_qualified_name (mono_reflection_type_get_handle ((MonoReflectionType*)arg), NULL);
                slen = strlen (str);
                if ((p-buffer) + 10 + slen >= *buflen) {
                        char *newbuf;
@@ -8994,11 +9711,12 @@ mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObj
 void
 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
 {
+       MonoError error;
        MonoClass *klass, *parent;
 
        MONO_ARCH_SAVE_REGS;
 
-       CHECK_MONOTYPE (tb->parent);
+       RESOLVE_TYPE (tb->parent);
 
        mono_loader_lock ();
 
@@ -9006,9 +9724,9 @@ mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
                /* check so we can compile corlib correctly */
                if (strcmp (mono_object_class (tb->parent)->name, "TypeBuilder") == 0) {
                        /* mono_class_setup_mono_type () guaranteess type->data.klass is valid */
-                       parent = monotype_cast (tb->parent)->type->data.klass;
+                       parent = mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent)->data.klass;
                } else {
-                       parent = mono_class_from_mono_type (monotype_cast (tb->parent)->type);
+                       parent = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent));
                }
        } else {
                parent = NULL;
@@ -9031,8 +9749,12 @@ mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
        klass->image = &tb->module->dynamic_image->image;
 
        klass->inited = 1; /* we lie to the runtime */
-       klass->name = mono_string_to_utf8_image (klass->image, tb->name);
-       klass->name_space = mono_string_to_utf8_image (klass->image, tb->nspace);
+       klass->name = mono_string_to_utf8_image (klass->image, tb->name, &error);
+       if (!mono_error_ok (&error))
+               goto failure;
+       klass->name_space = mono_string_to_utf8_image (klass->image, tb->nspace, &error);
+       if (!mono_error_ok (&error))
+               goto failure;
        klass->type_token = MONO_TOKEN_TYPE_DEF | tb->table_idx;
        klass->flags = tb->attrs;
        
@@ -9040,11 +9762,21 @@ mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
 
        klass->element_class = klass;
 
-       MOVING_GC_REGISTER (&klass->reflection_info);
-       klass->reflection_info = tb;
+       if (mono_class_get_ref_info (klass) == NULL) {
 
-       /* 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);
+               mono_class_set_ref_info (klass, tb);
+
+               /* Put into cache so mono_class_get () will find it.
+               Skip nested types as those should not be available on the global scope. */
+               if (!tb->nesting_type) {
+                       mono_image_add_to_name_cache (klass->image, klass->name_space, klass->name, tb->table_idx);
+               } else {
+                       klass->image->reflection_info_unregister_classes =
+                               g_slist_prepend (klass->image->reflection_info_unregister_classes, klass);
+               }
+       } else {
+               g_assert (mono_class_get_ref_info (klass) == tb);
+       }
 
        mono_g_hash_table_insert (tb->module->dynamic_image->tokens,
                GUINT_TO_POINTER (MONO_TOKEN_TYPE_DEF | tb->table_idx), tb);
@@ -9064,7 +9796,7 @@ mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
                        (!strcmp (klass->name, "Enum") && !strcmp (klass->name_space, "System"))) {
                klass->instance_size = sizeof (MonoObject);
                klass->size_inited = 1;
-               mono_class_setup_vtable_general (klass, NULL, 0);
+               mono_class_setup_vtable_general (klass, NULL, 0, NULL);
        }
 
        mono_class_setup_mono_type (klass);
@@ -9079,7 +9811,7 @@ mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
 
        if (tb->nesting_type) {
                g_assert (tb->nesting_type->type);
-               klass->nested_in = mono_class_from_mono_type (tb->nesting_type->type);
+               klass->nested_in = mono_class_from_mono_type (mono_reflection_type_get_handle (tb->nesting_type));
        }
 
        /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
@@ -9087,6 +9819,11 @@ mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
        mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
        
        mono_loader_unlock ();
+       return;
+
+failure:
+       mono_loader_unlock ();
+       mono_error_raise_exception (&error);
 }
 
 /*
@@ -9133,11 +9870,12 @@ mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
 
        for (i = 0; i < count; i++) {
                MonoReflectionGenericParam *gparam = mono_array_get (tb->generic_params, gpointer, i);
-               MonoGenericParamFull *param = (MonoGenericParamFull *) gparam->type.type->data.generic_param;
+               MonoGenericParamFull *param = (MonoGenericParamFull *) mono_reflection_type_get_handle ((MonoReflectionType*)gparam)->data.generic_param;
                klass->generic_container->type_params [i] = *param;
                /*Make sure we are a diferent type instance */
                klass->generic_container->type_params [i].param.owner = klass->generic_container;
                klass->generic_container->type_params [i].info.pklass = NULL;
+               klass->generic_container->type_params [i].info.flags = gparam->attrs;
 
                g_assert (klass->generic_container->type_params [i].param.owner);
        }
@@ -9171,12 +9909,12 @@ mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
 
                fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, 0);
 
-               if (!mono_type_is_valid_enum_basetype (monotype_cast (fb->type)->type)) {
+               if (!mono_type_is_valid_enum_basetype (mono_reflection_type_get_handle ((MonoReflectionType*)fb->type))) {
                        mono_loader_unlock ();
                        return;
                }
 
-               enum_basetype = monotype_cast (fb->type)->type;
+               enum_basetype = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
                klass->element_class = mono_class_from_mono_type (enum_basetype);
                if (!klass->element_class)
                        klass->element_class = mono_class_from_mono_type (enum_basetype);
@@ -9192,7 +9930,7 @@ mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
                 * to create objects of the enum type (for use in SetConstant).
                 */
                /* FIXME: Does this mean enums can't have method overrides ? */
-               mono_class_setup_vtable_general (klass, NULL, 0);
+               mono_class_setup_vtable_general (klass, NULL, 0, NULL);
        }
        mono_loader_unlock ();
 }
@@ -9229,7 +9967,7 @@ mono_marshal_spec_from_builder (MonoImage *image, MonoAssembly *assembly,
        case MONO_NATIVE_CUSTOM:
                if (minfo->marshaltyperef)
                        res->data.custom_data.custom_name =
-                               type_get_fully_qualified_name (monotype_cast (minfo->marshaltyperef)->type);
+                               type_get_fully_qualified_name (mono_reflection_type_get_handle ((MonoReflectionType*)minfo->marshaltyperef));
                if (minfo->mcookie)
                        res->data.custom_data.cookie = mono_string_to_utf8 (minfo->mcookie);
                break;
@@ -9296,14 +10034,16 @@ reflection_methodbuilder_to_mono_method (MonoClass *klass,
                                         ReflectionMethodBuilder *rmb,
                                         MonoMethodSignature *sig)
 {
+       MonoError error;
        MonoMethod *m;
-       MonoMethodNormal *pm;
+       MonoMethodWrapper *wrapperm;
        MonoMarshalSpec **specs;
        MonoReflectionMethodAux *method_aux;
        MonoImage *image;
        gboolean dynamic;
        int i;
 
+       mono_error_init (&error);
        /*
         * Methods created using a MethodBuilder should have their memory allocated
         * inside the image mempool, while dynamic methods should have their memory
@@ -9320,20 +10060,19 @@ reflection_methodbuilder_to_mono_method (MonoClass *klass,
        if ((rmb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
                        (rmb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
                m = (MonoMethod *)image_g_new0 (image, MonoMethodPInvoke, 1);
-       else if (rmb->refs)
-               m = (MonoMethod *)image_g_new0 (image, MonoMethodWrapper, 1);
        else
-               m = (MonoMethod *)image_g_new0 (image, MonoMethodNormal, 1);
+               m = (MonoMethod *)image_g_new0 (image, MonoMethodWrapper, 1);
 
-       pm = (MonoMethodNormal*)m;
+       wrapperm = (MonoMethodWrapper*)m;
 
        m->dynamic = dynamic;
        m->slot = -1;
        m->flags = rmb->attrs;
        m->iflags = rmb->iattrs;
-       m->name = mono_string_to_utf8_image (image, rmb->name);
+       m->name = mono_string_to_utf8_image_ignore (image, rmb->name);
        m->klass = klass;
        m->signature = sig;
+       m->sre_method = TRUE;
        m->skip_visibility = rmb->skip_visibility;
        if (rmb->table_idx)
                m->token = MONO_TOKEN_METHOD_DEF | (*rmb->table_idx);
@@ -9348,8 +10087,10 @@ reflection_methodbuilder_to_mono_method (MonoClass *klass,
 
                method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
 
-               method_aux->dllentry = rmb->dllentry ? mono_string_to_utf8_image (image, rmb->dllentry) : image_strdup (image, m->name);
-               method_aux->dll = mono_string_to_utf8_image (image, rmb->dll);
+               method_aux->dllentry = rmb->dllentry ? mono_string_to_utf8_image (image, rmb->dllentry, &error) : image_strdup (image, m->name);
+               g_assert (mono_error_ok (&error));
+               method_aux->dll = mono_string_to_utf8_image (image, rmb->dll, &error);
+               g_assert (mono_error_ok (&error));
                
                ((MonoMethodPInvoke*)m)->piflags = (rmb->native_cc << 8) | (rmb->charset ? (rmb->charset - 1) * 2 : 0) | rmb->extra_flags;
 
@@ -9389,8 +10130,7 @@ reflection_methodbuilder_to_mono_method (MonoClass *klass,
                        }
                }
 
-               header = image_g_malloc0 (image, sizeof (MonoMethodHeader) + 
-                       (num_locals - MONO_ZERO_LEN_ARRAY) * sizeof (MonoType*));
+               header = image_g_malloc0 (image, MONO_SIZEOF_METHOD_HEADER + num_locals * sizeof (MonoType*));
                header->code_size = code_size;
                header->code = image_g_malloc (image, code_size);
                memcpy ((char*)header->code, code, code_size);
@@ -9403,7 +10143,7 @@ reflection_methodbuilder_to_mono_method (MonoClass *klass,
                                mono_array_get (rmb->ilgen->locals, MonoReflectionLocalBuilder*, i);
 
                        header->locals [i] = image_g_new0 (image, MonoType, 1);
-                       memcpy (header->locals [i], monotype_cast (lb->type)->type, sizeof (MonoType));
+                       memcpy (header->locals [i], mono_reflection_type_get_handle ((MonoReflectionType*)lb->type), MONO_SIZEOF_TYPE);
                }
 
                header->num_clauses = num_clauses;
@@ -9412,29 +10152,46 @@ reflection_methodbuilder_to_mono_method (MonoClass *klass,
                                 rmb->ilgen, num_clauses);
                }
 
-               pm->header = header;
+               wrapperm->header = header;
        }
 
        if (rmb->generic_params) {
                int count = mono_array_length (rmb->generic_params);
-               MonoGenericContainer *container;
+               MonoGenericContainer *container = rmb->generic_container;
+
+               g_assert (container);
 
-               container = rmb->generic_container;
-               if (container) {
-                       m->is_generic = TRUE;
-                       mono_method_set_generic_container (m, container);
-               }
                container->type_argc = count;
                container->type_params = image_g_new0 (image, MonoGenericParamFull, count);
                container->owner.method = m;
 
+               m->is_generic = TRUE;
+               mono_method_set_generic_container (m, container);
+
                for (i = 0; i < count; i++) {
                        MonoReflectionGenericParam *gp =
                                mono_array_get (rmb->generic_params, MonoReflectionGenericParam*, i);
-                       MonoGenericParamFull *param = (MonoGenericParamFull *) gp->type.type->data.generic_param;
+                       MonoGenericParamFull *param = (MonoGenericParamFull *) mono_reflection_type_get_handle ((MonoReflectionType*)gp)->data.generic_param;
                        container->type_params [i] = *param;
                }
 
+               /*
+                * The method signature might have pointers to generic parameters that belong to other methods.
+                * This is a valid SRE case, but the resulting method signature must be encoded using the proper
+                * generic parameters.
+                */
+               for (i = 0; i < m->signature->param_count; ++i) {
+                       MonoType *t = m->signature->params [i];
+                       if (t->type == MONO_TYPE_MVAR) {
+                               MonoGenericParam *gparam =  t->data.generic_param;
+                               if (gparam->num < count) {
+                                       m->signature->params [i] = mono_metadata_type_dup (image, m->signature->params [i]);
+                                       m->signature->params [i]->data.generic_param = mono_generic_container_get_param (container, gparam->num);
+                               }
+
+                       }
+               }
+
                if (klass->generic_container) {
                        container->parent = klass->generic_container;
                        container->context.class_inst = klass->generic_container->context.class_inst;
@@ -9492,8 +10249,10 @@ reflection_methodbuilder_to_mono_method (MonoClass *klass,
                                        memcpy ((gpointer)method_aux->param_defaults [i], p, len);
                                }
 
-                               if (pb->name)
-                                       method_aux->param_names [i] = mono_string_to_utf8_image (image, pb->name);
+                               if (pb->name) {
+                                       method_aux->param_names [i] = mono_string_to_utf8_image (image, pb->name, &error);
+                                       g_assert (mono_error_ok (&error));
+                               }
                                if (pb->cattrs) {
                                        if (!method_aux->param_cattr)
                                                method_aux->param_cattr = image_g_new0 (image, MonoCustomAttrInfo*, m->signature->param_count + 1);
@@ -9583,20 +10342,23 @@ fieldbuilder_to_mono_class_field (MonoClass *klass, MonoReflectionFieldBuilder*
 {
        MonoClassField *field;
        MonoType *custom;
+       MonoError error;
 
        field = g_new0 (MonoClassField, 1);
 
-       field->name = mono_string_to_utf8 (fb->name);
+       field->name = mono_string_to_utf8_image (klass->image, fb->name, &error);
+       g_assert (mono_error_ok (&error));
        if (fb->attrs || fb->modreq || fb->modopt) {
-               field->type = mono_metadata_type_dup (NULL, monotype_cast (fb->type)->type);
+               field->type = mono_metadata_type_dup (NULL, mono_reflection_type_get_handle ((MonoReflectionType*)fb->type));
                field->type->attrs = fb->attrs;
 
                g_assert (klass->image->dynamic);
                custom = add_custom_modifiers ((MonoDynamicImage*)klass->image, field->type, fb->modreq, fb->modopt);
                g_free (field->type);
-               field->type = custom;
+               field->type = mono_metadata_type_dup (klass->image, custom);
+               g_free (custom);
        } else {
-               field->type = monotype_cast (fb->type)->type;
+               field->type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
        }
        if (fb->offset != -1)
                field->offset = fb->offset;
@@ -9622,29 +10384,32 @@ mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc
 
        domain = mono_object_domain (type);
 
-       if (!strcmp (((MonoObject *) type)->vtable->klass->name, "TypeBuilder")) {
+       if (is_sre_type_builder (mono_object_class (type))) {
                tb = (MonoReflectionTypeBuilder *) type;
 
                is_dynamic = TRUE;
-       } else if (!strcmp (((MonoObject *) type)->vtable->klass->name, "MonoGenericClass")) {
+       } else if (is_sre_generic_instance (mono_object_class (type))) {
                MonoReflectionGenericClass *rgi = (MonoReflectionGenericClass *) type;
+               MonoReflectionType *gtd = rgi->generic_type;
 
-               tb = rgi->generic_type;
-               is_dynamic = TRUE;
+               if (is_sre_type_builder (mono_object_class (gtd))) {
+                       tb = (MonoReflectionTypeBuilder *)gtd;
+                       is_dynamic = TRUE;
+               }
        }
 
        /* FIXME: fix the CreateGenericParameters protocol to avoid the two stage setup of TypeBuilders */
        if (tb && tb->generic_container)
                mono_reflection_create_generic_class (tb);
 
-       klass = mono_class_from_mono_type (type->type);
+       klass = mono_class_from_mono_type (mono_reflection_type_get_handle (type));
        if (!klass->generic_container) {
                mono_loader_unlock ();
                return NULL;
        }
 
        if (klass->wastypebuilder) {
-               tb = (MonoReflectionTypeBuilder *) klass->reflection_info;
+               tb = (MonoReflectionTypeBuilder *) mono_class_get_ref_info (klass);
 
                is_dynamic = TRUE;
        }
@@ -9683,6 +10448,7 @@ mono_reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, M
 
        MONO_ARCH_SAVE_REGS;
 
+       /*FIXME but this no longer should happen*/
        if (!strcmp (rmethod->object.vtable->klass->name, "MethodBuilder")) {
 #ifndef DISABLE_REFLECTION_EMIT
                MonoReflectionMethodBuilder *mb = NULL;
@@ -9691,7 +10457,7 @@ mono_reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, M
 
                mb = (MonoReflectionMethodBuilder *) rmethod;
                tb = (MonoReflectionTypeBuilder *) mb->type;
-               klass = mono_class_from_mono_type (tb->type.type);
+               klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
 
                method = methodbuilder_to_mono_method (klass, mb);
 #else
@@ -9714,7 +10480,7 @@ mono_reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, M
        type_argv = g_new0 (MonoType *, count);
        for (i = 0; i < count; i++) {
                MonoReflectionType *garg = mono_array_get (types, gpointer, i);
-               type_argv [i] = garg->type;
+               type_argv [i] = mono_reflection_type_get_handle (garg);
        }
        ginst = mono_metadata_get_generic_inst (count, type_argv);
        g_free (type_argv);
@@ -9725,6 +10491,7 @@ mono_reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, M
        inflated = mono_class_inflate_generic_method (method, &tmp_context);
        imethod = (MonoMethodInflated *) inflated;
 
+       /*FIXME but I think this is no longer necessary*/
        if (method->klass->image->dynamic) {
                MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
                /*
@@ -9735,6 +10502,9 @@ mono_reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, M
                mono_g_hash_table_insert (image->generic_def_objects, imethod, rmethod);
                mono_loader_unlock ();
        }
+
+       if (!mono_verifier_is_method_valid_generic_instantiation (inflated))
+               mono_raise_exception (mono_get_exception_argument ("typeArguments", "Invalid generic arguments"));
        
        return mono_method_get_object (mono_object_domain (rmethod), inflated, NULL);
 }
@@ -9758,7 +10528,7 @@ inflate_mono_method (MonoClass *klass, MonoMethod *method, MonoObject *obj)
 
        context = mono_class_get_context (klass);
 
-       if (klass->method.count) {
+       if (klass->method.count && klass->methods) {
                /* Find the already created inflated method */
                for (i = 0; i < klass->method.count; ++i) {
                        g_assert (klass->methods [i]->is_inflated);
@@ -9782,12 +10552,24 @@ inflate_mono_method (MonoClass *klass, MonoMethod *method, MonoObject *obj)
 }
 
 static MonoMethod *
-inflate_method (MonoReflectionGenericClass *type, MonoObject *obj)
+inflate_method (MonoReflectionType *type, MonoObject *obj)
 {
        MonoMethod *method;
        MonoClass *gklass;
 
-       gklass = mono_class_from_mono_type (type->generic_type->type.type);
+       MonoClass *type_class = mono_object_class (type);
+
+       if (is_sre_generic_instance (type_class)) {
+               MonoReflectionGenericClass *mgc = (MonoReflectionGenericClass*)type;
+               gklass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)mgc->generic_type));
+       } else if (is_sre_type_builder (type_class)) {
+               gklass = mono_class_from_mono_type (mono_reflection_type_get_handle (type));
+       } else if (type->type) {
+               gklass = mono_class_from_mono_type (type->type);
+               gklass = mono_class_get_generic_type_definition (gklass);
+       } else {
+               g_error ("Can't handle type %s", mono_type_get_full_name (mono_object_class (type)));
+       }
 
        if (!strcmp (obj->vtable->klass->name, "MethodBuilder"))
                if (((MonoReflectionMethodBuilder*)obj)->mhandle)
@@ -9800,10 +10582,10 @@ inflate_method (MonoReflectionGenericClass *type, MonoObject *obj)
                method = ((MonoReflectionMethod *) obj)->method;
        else {
                method = NULL; /* prevent compiler warning */
-               g_assert_not_reached ();
+               g_error ("can't handle type %s", obj->vtable->klass->name);
        }
 
-       return inflate_mono_method (mono_class_from_mono_type (type->type.type), method, obj);
+       return inflate_mono_method (mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)type)), method, obj);
 }
 
 /*TODO avoid saving custom attrs for generic classes as it's enough to have them on the generic type definition.*/
@@ -9815,15 +10597,19 @@ mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, Mono
        MonoGenericClass *gclass;
        MonoDynamicGenericClass *dgclass;
        MonoClass *klass, *gklass;
+       MonoType *gtype;
        int i;
 
        MONO_ARCH_SAVE_REGS;
 
-       klass = mono_class_from_mono_type (type->type.type);
-       g_assert (type->type.type->type == MONO_TYPE_GENERICINST);
-       gclass = type->type.type->data.generic_class;
+       gtype = mono_reflection_type_get_handle ((MonoReflectionType*)type);
+       klass = mono_class_from_mono_type (gtype);
+       g_assert (gtype->type == MONO_TYPE_GENERICINST);
+       gclass = gtype->data.generic_class;
+
+       if (!gclass->is_dynamic)
+               return;
 
-       g_assert (gclass->is_dynamic);
        dgclass = (MonoDynamicGenericClass *) gclass;
 
        if (dgclass->initialized)
@@ -9835,27 +10621,23 @@ mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, Mono
        dgclass->count_methods = methods ? mono_array_length (methods) : 0;
        dgclass->count_ctors = ctors ? mono_array_length (ctors) : 0;
        dgclass->count_fields = fields ? mono_array_length (fields) : 0;
-       dgclass->count_properties = properties ? mono_array_length (properties) : 0;
-       dgclass->count_events = events ? mono_array_length (events) : 0;
 
-       dgclass->methods = g_new0 (MonoMethod *, dgclass->count_methods);
-       dgclass->ctors = g_new0 (MonoMethod *, dgclass->count_ctors);
-       dgclass->fields = g_new0 (MonoClassField, dgclass->count_fields);
-       dgclass->properties = g_new0 (MonoProperty, dgclass->count_properties);
-       dgclass->events = g_new0 (MonoEvent, dgclass->count_events);
-       dgclass->field_objects = g_new0 (MonoObject*, dgclass->count_fields);
-       dgclass->field_generic_types = g_new0 (MonoType*, dgclass->count_fields);
+       dgclass->methods = mono_image_set_new0 (gclass->owner, MonoMethod *, dgclass->count_methods);
+       dgclass->ctors = mono_image_set_new0 (gclass->owner, MonoMethod *, dgclass->count_ctors);
+       dgclass->fields = mono_image_set_new0 (gclass->owner, MonoClassField, dgclass->count_fields);
+       dgclass->field_objects = mono_image_set_new0 (gclass->owner, MonoObject*, dgclass->count_fields);
+       dgclass->field_generic_types = mono_image_set_new0 (gclass->owner, MonoType*, dgclass->count_fields);
 
        for (i = 0; i < dgclass->count_methods; i++) {
                MonoObject *obj = mono_array_get (methods, gpointer, i);
 
-               dgclass->methods [i] = inflate_method (type, obj);
+               dgclass->methods [i] = inflate_method ((MonoReflectionType*)type, obj);
        }
 
        for (i = 0; i < dgclass->count_ctors; i++) {
                MonoObject *obj = mono_array_get (ctors, gpointer, i);
 
-               dgclass->ctors [i] = inflate_method (type, obj);
+               dgclass->ctors [i] = inflate_method ((MonoReflectionType*)type, obj);
        }
 
        for (i = 0; i < dgclass->count_fields; i++) {
@@ -9876,100 +10658,105 @@ mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, Mono
                dgclass->fields [i].type = mono_class_inflate_generic_type (
                        field->type, mono_generic_class_get_context ((MonoGenericClass *) dgclass));
                dgclass->field_generic_types [i] = field->type;
-               MOVING_GC_REGISTER (&dgclass->field_objects [i]);
+               MONO_GC_REGISTER_ROOT_IF_MOVING (dgclass->field_objects [i]);
                dgclass->field_objects [i] = obj;
 
                if (inflated_field) {
                        g_free (inflated_field);
                } else {
-                       dgclass->fields [i].name = g_strdup (dgclass->fields [i].name);
+                       dgclass->fields [i].name = mono_image_set_strdup (gclass->owner, dgclass->fields [i].name);
                }
        }
 
-       for (i = 0; i < dgclass->count_properties; i++) {
-               MonoObject *obj = mono_array_get (properties, gpointer, i);
-               MonoProperty *property = &dgclass->properties [i];
+       dgclass->initialized = TRUE;
+}
 
-               if (!strcmp (obj->vtable->klass->name, "PropertyBuilder")) {
-                       MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *) obj;
+void
+mono_reflection_free_dynamic_generic_class (MonoGenericClass *gclass)
+{
+       MonoDynamicGenericClass *dgclass;
+       int i;
 
-                       property->parent = klass;
-                       property->attrs = pb->attrs;
-                       property->name = mono_string_to_utf8 (pb->name);
-                       if (pb->get_method)
-                               property->get = inflate_method (type, (MonoObject *) pb->get_method);
-                       if (pb->set_method)
-                               property->set = inflate_method (type, (MonoObject *) pb->set_method);
-               } else if (!strcmp (obj->vtable->klass->name, "MonoProperty")) {
-                       *property = *((MonoReflectionProperty *) obj)->property;
-                       property->name = g_strdup (property->name);
+       g_assert (gclass->is_dynamic);
 
-                       if (property->get)
-                               property->get = inflate_mono_method (klass, property->get, NULL);
-                       if (property->set)
-                               property->set = inflate_mono_method (klass, property->set, NULL);
-               } else
-                       g_assert_not_reached ();
-       }
+       dgclass = (MonoDynamicGenericClass *)gclass;
 
-       for (i = 0; i < dgclass->count_events; i++) {
-               MonoObject *obj = mono_array_get (events, gpointer, i);
-               MonoEvent *event = &dgclass->events [i];
-
-               if (!strcmp (obj->vtable->klass->name, "EventBuilder")) {
-                       MonoReflectionEventBuilder *eb = (MonoReflectionEventBuilder *) obj;
-
-                       event->parent = klass;
-                       event->attrs = eb->attrs;
-                       event->name = mono_string_to_utf8 (eb->name);
-                       if (eb->add_method)
-                               event->add = inflate_method (type, (MonoObject *) eb->add_method);
-                       if (eb->remove_method)
-                               event->remove = inflate_method (type, (MonoObject *) eb->remove_method);
-               } else if (!strcmp (obj->vtable->klass->name, "MonoEvent")) {
-                       *event = *((MonoReflectionMonoEvent *) obj)->event;
-                       event->name = g_strdup (event->name);
-
-                       if (event->add)
-                               event->add = inflate_mono_method (klass, event->add, NULL);
-                       if (event->remove)
-                               event->remove = inflate_mono_method (klass, event->remove, NULL);
-               } else
-                       g_assert_not_reached ();
+       for (i = 0; i < dgclass->count_fields; ++i) {
+               MonoClassField *field = dgclass->fields + i;
+               mono_metadata_free_type (field->type);
+               MONO_GC_UNREGISTER_ROOT_IF_MOVING (dgclass->field_objects [i]);
        }
-
-       dgclass->initialized = TRUE;
 }
 
 static void
-ensure_generic_class_runtime_vtable (MonoClass *klass)
+fix_partial_generic_class (MonoClass *klass)
 {
        MonoClass *gklass = klass->generic_class->container_class;
+       MonoDynamicGenericClass *dgclass;
        int i;
 
        if (klass->wastypebuilder)
                return;
 
-       ensure_runtime_vtable (gklass);
+       dgclass = (MonoDynamicGenericClass *)  klass->generic_class;
+       if (klass->parent != gklass->parent) {
+               MonoError error;
+               MonoType *parent_type = mono_class_inflate_generic_type_checked (&gklass->parent->byval_arg, &klass->generic_class->context, &error);
+               if (mono_error_ok (&error)) {
+                       MonoClass *parent = mono_class_from_mono_type (parent_type);
+                       mono_metadata_free_type (parent_type);
+                       if (parent != klass->parent) {
+                               /*fool mono_class_setup_parent*/
+                               klass->supertypes = NULL;
+                               mono_class_setup_parent (klass, parent);
+                       }
+               } else {
+                       mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
+                       mono_error_cleanup (&error);
+                       if (gklass->wastypebuilder)
+                               klass->wastypebuilder = TRUE;
+                       return;
+               }
+       }
+
+       if (!dgclass->initialized)
+               return;
+
+       if (klass->method.count != gklass->method.count) {
+               klass->method.count = gklass->method.count;
+               klass->methods = mono_image_alloc (klass->image, sizeof (MonoMethod*) * (klass->method.count + 1));
+
+               for (i = 0; i < klass->method.count; i++) {
+                       klass->methods [i] = mono_class_inflate_generic_method_full (
+                               gklass->methods [i], klass, mono_class_get_context (klass));
+               }
+       }
+
+       if (klass->interface_count && klass->interface_count != gklass->interface_count) {
+               klass->interface_count = gklass->interface_count;
+               klass->interfaces = mono_image_alloc (klass->image, sizeof (MonoClass*) * gklass->interface_count);
+               klass->interfaces_packed = NULL; /*make setup_interface_offsets happy*/
 
-       klass->method.count = gklass->method.count;
-       klass->methods = mono_image_alloc (klass->image, sizeof (MonoMethod*) * (klass->method.count + 1));
+               for (i = 0; i < gklass->interface_count; ++i) {
+                       MonoType *iface_type = mono_class_inflate_generic_type (&gklass->interfaces [i]->byval_arg, mono_class_get_context (klass));
+                       klass->interfaces [i] = mono_class_from_mono_type (iface_type);
+                       mono_metadata_free_type (iface_type);
 
-       for (i = 0; i < klass->method.count; i++) {
-               klass->methods [i] = mono_class_inflate_generic_method_full (
-                       gklass->methods [i], klass, mono_class_get_context (klass));
+                       ensure_runtime_vtable (klass->interfaces [i]);
+               }
+               klass->interfaces_inited = 1;
        }
 
-       klass->interface_count = gklass->interface_count;
-       klass->interfaces = mono_image_alloc (klass->image, sizeof (MonoClass*) * klass->interface_count);
-       for (i = 0; i < klass->interface_count; ++i) {
-               MonoType *iface_type = mono_class_inflate_generic_type (&gklass->interfaces [i]->byval_arg, mono_class_get_context (klass));
-               klass->interfaces [i] = mono_class_from_mono_type (iface_type);
-               mono_metadata_free_type (iface_type);
+       if (klass->field.count != gklass->field.count) {
+               klass->field.count = gklass->field.count;
+               klass->fields = image_g_new0 (klass->image, MonoClassField, klass->field.count);
 
-               ensure_runtime_vtable (klass->interfaces [i]);
+               for (i = 0; i < klass->field.count; i++) {
+                       klass->fields [i] = gklass->fields [i];
+                       klass->fields [i].parent = klass;
+                       klass->fields [i].type = mono_class_inflate_generic_type (gklass->fields [i].type, mono_class_get_context (klass));
+               }
        }
-       klass->interfaces_inited = 1;
 
        /*We can only finish with this klass once it's parent has as well*/
        if (gklass->wastypebuilder)
@@ -9977,10 +10764,20 @@ ensure_generic_class_runtime_vtable (MonoClass *klass)
        return;
 }
 
+static void
+ensure_generic_class_runtime_vtable (MonoClass *klass)
+{
+       MonoClass *gklass = klass->generic_class->container_class;
+
+       ensure_runtime_vtable (gklass); 
+
+       fix_partial_generic_class (klass);
+}
+
 static void
 ensure_runtime_vtable (MonoClass *klass)
 {
-       MonoReflectionTypeBuilder *tb = klass->reflection_info;
+       MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
        int i, num, j;
 
        if (!klass->image->dynamic || (!tb && !klass->generic_class) || klass->wastypebuilder)
@@ -10005,8 +10802,8 @@ ensure_runtime_vtable (MonoClass *klass)
                        klass->interface_count = mono_array_length (tb->interfaces);
                        klass->interfaces = mono_image_alloc (klass->image, sizeof (MonoClass*) * klass->interface_count);
                        for (i = 0; i < klass->interface_count; ++i) {
-                               MonoReflectionType *iface = mono_type_array_get (tb->interfaces, i);
-                               klass->interfaces [i] = mono_class_from_mono_type (iface->type);
+                               MonoType *iface = mono_type_array_get_and_resolve (tb->interfaces, i);
+                               klass->interfaces [i] = mono_class_from_mono_type (iface);
                                ensure_runtime_vtable (klass->interfaces [i]);
                        }
                        klass->interfaces_inited = 1;
@@ -10016,9 +10813,14 @@ ensure_runtime_vtable (MonoClass *klass)
        }
 
        if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
-               for (i = 0; i < klass->method.count; ++i)
-                       klass->methods [i]->slot = i;
+               int slot_num = 0;
+               for (i = 0; i < klass->method.count; ++i) {
+                       MonoMethod *im = klass->methods [i];
+                       if (!(im->flags & METHOD_ATTRIBUTE_STATIC))
+                               im->slot = slot_num++;
+               }
                
+               klass->interfaces_packed = NULL; /*make setup_interface_offsets happy*/
                mono_class_setup_interface_offsets (klass);
                mono_class_setup_interface_id (klass);
        }
@@ -10035,6 +10837,45 @@ ensure_runtime_vtable (MonoClass *klass)
         */
 }
 
+static MonoMethod*
+mono_reflection_method_get_handle (MonoObject *method)
+{
+       MonoClass *class = mono_object_class (method);
+       if (is_sr_mono_method (class) || is_sr_mono_generic_method (class)) {
+               MonoReflectionMethod *sr_method = (MonoReflectionMethod*)method;
+               return sr_method->method;
+       }
+       if (is_sre_method_builder (class)) {
+               MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)method;
+               return mb->mhandle;
+       }
+       if (is_sre_method_on_tb_inst (class)) {
+               MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)method;
+               MonoMethod *result;
+               /*FIXME move this to a proper method and unify with resolve_object*/
+               if (m->method_args) {
+                       result = mono_reflection_method_on_tb_inst_get_handle (m);
+               } else {
+                       MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst);
+                       MonoClass *inflated_klass = mono_class_from_mono_type (type);
+                       MonoMethod *mono_method;
+
+                       if (is_sre_method_builder (mono_object_class (m->mb)))
+                               mono_method = ((MonoReflectionMethodBuilder *)m->mb)->mhandle;
+                       else if (is_sr_mono_method (mono_object_class (m->mb)))
+                               mono_method = ((MonoReflectionMethod *)m->mb)->method;
+                       else
+                               g_error ("resolve_object:: can't handle a MTBI with base_method of type %s", mono_type_get_full_name (mono_object_class (m->mb)));
+
+                       result = inflate_mono_method (inflated_klass, mono_method, (MonoObject*)m->mb);
+               }
+               return result;
+       }
+
+       g_error ("Can't handle methods of type %s:%s", class->name_space, class->name);
+       return NULL;
+}
+
 void
 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides)
 {
@@ -10046,12 +10887,12 @@ mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides
 
        g_assert (klass->image->dynamic);
 
-       if (!klass->reflection_info)
+       if (!mono_class_get_ref_info (klass))
                return;
 
-       g_assert (strcmp (((MonoObject*)klass->reflection_info)->vtable->klass->name, "TypeBuilder") == 0);
+       g_assert (strcmp (((MonoObject*)mono_class_get_ref_info (klass))->vtable->klass->name, "TypeBuilder") == 0);
 
-       tb = (MonoReflectionTypeBuilder*)klass->reflection_info;
+       tb = (MonoReflectionTypeBuilder*)mono_class_get_ref_info (klass);
 
        onum = 0;
        if (tb->methods) {
@@ -10071,13 +10912,9 @@ mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides
                        MonoReflectionMethodBuilder *mb = 
                                mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
                        if (mb->override_method) {
-                               (*overrides) [onum * 2] = 
-                                       mb->override_method->method;
-                               (*overrides) [onum * 2 + 1] =
-                                       mb->mhandle;
+                               (*overrides) [onum * 2] = mono_reflection_method_get_handle ((MonoObject *)mb->override_method);
+                               (*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 ++;
@@ -10089,9 +10926,9 @@ mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides
 }
 
 static void
-typebuilder_setup_fields (MonoClass *klass)
+typebuilder_setup_fields (MonoClass *klass, MonoError *error)
 {
-       MonoReflectionTypeBuilder *tb = klass->reflection_info;
+       MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
        MonoReflectionFieldBuilder *fb;
        MonoClassField *field;
        MonoImage *image = klass->image;
@@ -10102,6 +10939,8 @@ typebuilder_setup_fields (MonoClass *klass)
        klass->field.count = tb->num_fields;
        klass->field.first = 0;
 
+       mono_error_init (error);
+
        if (tb->class_size) {
                g_assert ((tb->packing_size & 0xfffffff0) == 0);
                klass->packing_size = tb->packing_size;
@@ -10116,16 +10955,26 @@ typebuilder_setup_fields (MonoClass *klass)
        klass->fields = image_g_new0 (image, MonoClassField, klass->field.count);
        mono_class_alloc_ext (klass);
        klass->ext->field_def_values = image_g_new0 (image, MonoFieldDefaultValue, klass->field.count);
+       /*
+       This is, guess what, a hack.
+       The issue is that the runtime doesn't know how to setup the fields of a typebuider and crash.
+       On the static path no field class is resolved, only types are built. This is the right thing to do
+       but we suck.
+       Setting size_inited is harmless because we're doing the same job as mono_class_setup_fields anyway.
+       */
+       klass->size_inited = 1;
 
        for (i = 0; i < klass->field.count; ++i) {
                fb = mono_array_get (tb->fields, gpointer, i);
                field = &klass->fields [i];
-               field->name = mono_string_to_utf8_image (image, fb->name);
+               field->name = mono_string_to_utf8_image (image, fb->name, error);
+               if (!mono_error_ok (error))
+                       return;
                if (fb->attrs) {
-                       field->type = mono_metadata_type_dup (klass->image, monotype_cast (fb->type)->type);
+                       field->type = mono_metadata_type_dup (klass->image, mono_reflection_type_get_handle ((MonoReflectionType*)fb->type));
                        field->type->attrs = fb->attrs;
                } else {
-                       field->type = monotype_cast (fb->type)->type;
+                       field->type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
                }
                if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && fb->rva_data)
                        klass->ext->field_def_values [i].data = mono_array_addr (fb->rva_data, char, 0);
@@ -10135,6 +10984,9 @@ typebuilder_setup_fields (MonoClass *klass)
                fb->handle = field;
                mono_save_custom_attrs (klass->image, field, fb->cattrs);
 
+               if (klass->enumtype && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
+                       klass->cast_class = klass->element_class = mono_class_from_mono_type (field->type);
+               }
                if (fb->def_value) {
                        MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
                        field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
@@ -10153,14 +11005,16 @@ typebuilder_setup_fields (MonoClass *klass)
 }
 
 static void
-typebuilder_setup_properties (MonoClass *klass)
+typebuilder_setup_properties (MonoClass *klass, MonoError *error)
 {
-       MonoReflectionTypeBuilder *tb = klass->reflection_info;
+       MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
        MonoReflectionPropertyBuilder *pb;
        MonoImage *image = klass->image;
        MonoProperty *properties;
        int i;
 
+       mono_error_init (error);
+
        if (!klass->ext)
                klass->ext = image_g_new0 (image, MonoClassExt, 1);
 
@@ -10173,13 +11027,30 @@ typebuilder_setup_properties (MonoClass *klass)
                pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
                properties [i].parent = klass;
                properties [i].attrs = pb->attrs;
-               properties [i].name = mono_string_to_utf8_image (image, pb->name);
+               properties [i].name = mono_string_to_utf8_image (image, pb->name, error);
+               if (!mono_error_ok (error))
+                       return;
                if (pb->get_method)
                        properties [i].get = pb->get_method->mhandle;
                if (pb->set_method)
                        properties [i].set = pb->set_method->mhandle;
 
                mono_save_custom_attrs (klass->image, &properties [i], pb->cattrs);
+               if (pb->def_value) {
+                       guint32 len, idx;
+                       const char *p, *p2;
+                       MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
+                       if (!klass->ext->prop_def_values)
+                               klass->ext->prop_def_values = image_g_new0 (image, MonoFieldDefaultValue, klass->ext->property.count);
+                       properties [i].attrs |= PROPERTY_ATTRIBUTE_HAS_DEFAULT;
+                       idx = encode_constant (assembly, pb->def_value, &klass->ext->prop_def_values [i].def_type);
+                       /* Copy the data from the blob since it might get realloc-ed */
+                       p = assembly->blob.data + idx;
+                       len = mono_metadata_decode_blob_size (p, &p2);
+                       len += p2 - p;
+                       klass->ext->prop_def_values [i].data = mono_image_alloc (image, len);
+                       memcpy ((gpointer)klass->ext->prop_def_values [i].data, p, len);
+               }
        }
 }
 
@@ -10188,9 +11059,8 @@ mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, Mon
 {
        MonoEvent *event = g_new0 (MonoEvent, 1);
        MonoClass *klass;
-       int j;
 
-       klass = mono_class_from_mono_type (tb->type.type);
+       klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
 
        event->parent = klass;
        event->attrs = eb->attrs;
@@ -10202,7 +11072,9 @@ mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, Mon
        if (eb->raise_method)
                event->raise = eb->raise_method->mhandle;
 
+#ifndef MONO_SMALL_CONFIG
        if (eb->other_methods) {
+               int j;
                event->other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods) + 1);
                for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
                        MonoReflectionMethodBuilder *mb = 
@@ -10211,18 +11083,21 @@ mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, Mon
                        event->other [j] = mb->mhandle;
                }
        }
+#endif
 
        return mono_event_get_object (mono_object_domain (tb), klass, event);
 }
 
 static void
-typebuilder_setup_events (MonoClass *klass)
+typebuilder_setup_events (MonoClass *klass, MonoError *error)
 {
-       MonoReflectionTypeBuilder *tb = klass->reflection_info;
+       MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
        MonoReflectionEventBuilder *eb;
        MonoImage *image = klass->image;
        MonoEvent *events;
-       int i, j;
+       int i;
+
+       mono_error_init (error);
 
        if (!klass->ext)
                klass->ext = image_g_new0 (image, MonoClassExt, 1);
@@ -10236,7 +11111,9 @@ typebuilder_setup_events (MonoClass *klass)
                eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
                events [i].parent = klass;
                events [i].attrs = eb->attrs;
-               events [i].name = mono_string_to_utf8_image (image, eb->name);
+               events [i].name = mono_string_to_utf8_image (image, eb->name, error);
+               if (!mono_error_ok (error))
+                       return;
                if (eb->add_method)
                        events [i].add = eb->add_method->mhandle;
                if (eb->remove_method)
@@ -10244,7 +11121,9 @@ typebuilder_setup_events (MonoClass *klass)
                if (eb->raise_method)
                        events [i].raise = eb->raise_method->mhandle;
 
+#ifndef MONO_SMALL_CONFIG
                if (eb->other_methods) {
+                       int j;
                        events [i].other = image_g_new0 (image, MonoMethod*, mono_array_length (eb->other_methods) + 1);
                        for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
                                MonoReflectionMethodBuilder *mb = 
@@ -10253,21 +11132,23 @@ typebuilder_setup_events (MonoClass *klass)
                                events [i].other [j] = mb->mhandle;
                        }
                }
+#endif
                mono_save_custom_attrs (klass->image, &events [i], eb->cattrs);
        }
 }
 
 static gboolean
-remove_instantiations_of (gpointer key,
+remove_instantiations_of_and_ensure_contents (gpointer key,
                                                  gpointer value,
                                                  gpointer user_data)
 {
        MonoType *type = (MonoType*)key;
        MonoClass *klass = (MonoClass*)user_data;
 
-       if ((type->type == MONO_TYPE_GENERICINST) && (type->data.generic_class->container_class == klass))
+       if ((type->type == MONO_TYPE_GENERICINST) && (type->data.generic_class->container_class == klass)) {
+               fix_partial_generic_class (mono_class_from_mono_type (type)); //Ensure it's safe to use it.
                return TRUE;
-       else
+       else
                return FALSE;
 }
 
@@ -10280,12 +11161,13 @@ check_array_for_usertypes (MonoArray *arr)
                return;
 
        for (i = 0; i < mono_array_length (arr); ++i)
-               CHECK_MONOTYPE (mono_array_get (arr, gpointer, i));
+               RESOLVE_ARRAY_TYPE_ELEMENT (arr, i);
 }
 
 MonoReflectionType*
 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
 {
+       MonoError error;
        MonoClass *klass;
        MonoDomain* domain;
        MonoReflectionType* res;
@@ -10299,17 +11181,17 @@ mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
        /*
         * Check for user defined Type subclasses.
         */
-       CHECK_MONOTYPE (tb->parent);
+       RESOLVE_TYPE (tb->parent);
        check_array_for_usertypes (tb->interfaces);
        if (tb->fields) {
                for (i = 0; i < mono_array_length (tb->fields); ++i) {
                        MonoReflectionFieldBuilder *fb = mono_array_get (tb->fields, gpointer, i);
                        if (fb) {
-                               CHECK_MONOTYPE (fb->type);
+                               RESOLVE_TYPE (fb->type);
                                check_array_for_usertypes (fb->modreq);
                                check_array_for_usertypes (fb->modopt);
                                if (fb->marshal_info && fb->marshal_info->marshaltyperef)
-                                       CHECK_MONOTYPE (fb->marshal_info->marshaltyperef);
+                                       RESOLVE_TYPE (fb->marshal_info->marshaltyperef);
                        }
                }
        }
@@ -10317,7 +11199,7 @@ mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
                for (i = 0; i < mono_array_length (tb->methods); ++i) {
                        MonoReflectionMethodBuilder *mb = mono_array_get (tb->methods, gpointer, i);
                        if (mb) {
-                               CHECK_MONOTYPE (mb->rtype);
+                               RESOLVE_TYPE (mb->rtype);
                                check_array_for_usertypes (mb->return_modreq);
                                check_array_for_usertypes (mb->return_modopt);
                                check_array_for_usertypes (mb->parameters);
@@ -10365,6 +11247,12 @@ mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
        klass->flags = tb->attrs;
        klass->has_cctor = 1;
        klass->has_finalize = 1;
+       klass->has_finalize_inited = 1;
+
+       /* fool mono_class_setup_parent */
+       klass->supertypes = NULL;
+       mono_class_setup_parent (klass, klass->parent);
+       mono_class_setup_mono_type (klass);
 
 #if 0
        if (!((MonoDynamicImage*)klass->image)->run) {
@@ -10386,7 +11274,7 @@ mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
                for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
                        MonoReflectionTypeBuilder *subtb = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
                        mono_class_alloc_ext (klass);
-                       klass->ext->nested_classes = g_list_prepend_image (klass->image, klass->ext->nested_classes, mono_class_from_mono_type (subtb->type.type));
+                       klass->ext->nested_classes = g_list_prepend_image (klass->image, klass->ext->nested_classes, mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)subtb)));
                }
        }
 
@@ -10409,21 +11297,28 @@ mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
        }
 
        /* FIXME: handle packing_size and instance_size */
-       typebuilder_setup_fields (klass);
+       typebuilder_setup_fields (klass, &error);
+       if (!mono_error_ok (&error))
+               goto failure;
+       typebuilder_setup_properties (klass, &error);
+       if (!mono_error_ok (&error))
+               goto failure;
 
-       typebuilder_setup_properties (klass);
+       typebuilder_setup_events (klass, &error);
+       if (!mono_error_ok (&error))
+               goto failure;
 
-       typebuilder_setup_events (klass);
-       
        klass->wastypebuilder = TRUE;
 
        /* 
         * If we are a generic TypeBuilder, there might be instantiations in the type cache
         * which have type System.Reflection.MonoGenericClass, but after the type is created, 
         * we want to return normal System.MonoType objects, so clear these out from the cache.
+        *
+        * Together with this we must ensure the contents of all instances to match the created type.
         */
        if (domain->type_hash && klass->generic_container)
-               mono_g_hash_table_foreach_remove (domain->type_hash, remove_instantiations_of, klass);
+               mono_g_hash_table_foreach_remove (domain->type_hash, remove_instantiations_of_and_ensure_contents, klass);
 
        mono_domain_unlock (domain);
        mono_loader_unlock ();
@@ -10437,6 +11332,14 @@ mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
        g_assert (res != (MonoReflectionType*)tb);
 
        return res;
+
+failure:
+       mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
+       klass->wastypebuilder = TRUE;
+       mono_domain_unlock (domain);
+       mono_loader_unlock ();
+       mono_error_raise_exception (&error);
+       return NULL;
 }
 
 void
@@ -10445,15 +11348,22 @@ mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam
        MonoGenericParamFull *param;
        MonoImage *image;
        MonoClass *pklass;
+       MonoError error;
 
        MONO_ARCH_SAVE_REGS;
 
-       param = g_new0 (MonoGenericParamFull, 1);
+       image = &gparam->tbuilder->module->dynamic_image->image;
+
+       param = mono_image_new0 (image, MonoGenericParamFull, 1);
+
+       param->info.name = mono_string_to_utf8_image (image, gparam->name, &error);
+       g_assert (mono_error_ok (&error));
+       param->param.num = gparam->index;
 
        if (gparam->mbuilder) {
                if (!gparam->mbuilder->generic_container) {
                        MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)gparam->mbuilder->type;
-                       MonoClass *klass = mono_class_from_mono_type (tb->type.type);
+                       MonoClass *klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
                        gparam->mbuilder->generic_container = mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
                        gparam->mbuilder->generic_container->is_method = TRUE;
                        /* 
@@ -10465,29 +11375,28 @@ mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam
                param->param.owner = gparam->mbuilder->generic_container;
        } else if (gparam->tbuilder) {
                if (!gparam->tbuilder->generic_container) {
-                       MonoClass *klass = mono_class_from_mono_type (gparam->tbuilder->type.type);
+                       MonoClass *klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)gparam->tbuilder));
                        gparam->tbuilder->generic_container = mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
                        gparam->tbuilder->generic_container->owner.klass = klass;
                }
                param->param.owner = gparam->tbuilder->generic_container;
        }
 
-       param->info.name = mono_string_to_utf8 (gparam->name);
-       param->param.num = gparam->index;
-
-       image = &gparam->tbuilder->module->dynamic_image->image;
        pklass = mono_class_from_generic_parameter ((MonoGenericParam *) param, image, gparam->mbuilder != NULL);
 
        gparam->type.type = &pklass->byval_arg;
 
-       MOVING_GC_REGISTER (&pklass->reflection_info);
-       pklass->reflection_info = gparam; /* FIXME: GC pin gparam */
+       mono_class_set_ref_info (pklass, gparam);
+       mono_image_lock (image);
+       image->reflection_info_unregister_classes = g_slist_prepend (image->reflection_info_unregister_classes, pklass);
+       mono_image_unlock (image);
 }
 
 MonoArray *
 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
 {
-       MonoDynamicImage *assembly = sig->module->dynamic_image;
+       MonoReflectionModuleBuilder *module = sig->module;
+       MonoDynamicImage *assembly = module != NULL ? module->dynamic_image : NULL;
        guint32 na = sig->arguments ? mono_array_length (sig->arguments) : 0;
        guint32 buflen, i;
        MonoArray *result;
@@ -10499,9 +11408,11 @@ mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
 
        sigbuffer_add_value (&buf, 0x07);
        sigbuffer_add_value (&buf, na);
-       for (i = 0; i < na; ++i) {
-               MonoReflectionType *type = mono_type_array_get (sig->arguments, i);
-               encode_reflection_type (assembly, type, &buf);
+       if (assembly != NULL){
+               for (i = 0; i < na; ++i) {
+                       MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType*, i);
+                       encode_reflection_type (assembly, type, &buf);
+               }
        }
 
        buflen = buf.p - buf.buf;
@@ -10527,7 +11438,7 @@ mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
 
        sigbuffer_add_value (&buf, 0x06);
        for (i = 0; i < na; ++i) {
-               MonoReflectionType *type = mono_type_array_get (sig->arguments, i);
+               MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType*, i);
                encode_reflection_type (assembly, type, &buf);
        }
 
@@ -10539,15 +11450,47 @@ mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
        return result;
 }
 
+typedef struct {
+       MonoMethod *handle;
+       MonoDomain *domain;
+} DynamicMethodReleaseData;
+
+/*
+ * The runtime automatically clean up those after finalization.
+*/     
+static MonoReferenceQueue *dynamic_method_queue;
+
+static void
+free_dynamic_method (void *dynamic_method)
+{
+       DynamicMethodReleaseData *data = dynamic_method;
+
+       mono_runtime_free_method (data->domain, data->handle);
+       g_free (data);
+}
+
 void 
 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
 {
+       MonoReferenceQueue *queue;
+       MonoMethod *handle;
+       DynamicMethodReleaseData *release_data;
        ReflectionMethodBuilder rmb;
        MonoMethodSignature *sig;
        MonoClass *klass;
        GSList *l;
        int i;
 
+       if (mono_runtime_is_shutting_down ())
+               mono_raise_exception (mono_get_exception_invalid_operation (""));
+
+       if (!(queue = dynamic_method_queue)) {
+               mono_loader_lock ();
+               if (!(queue = dynamic_method_queue))
+                       queue = dynamic_method_queue = mono_gc_reference_queue_new (free_dynamic_method);
+               mono_loader_unlock ();
+       }
+
        sig = dynamic_method_to_signature (mb);
 
        reflection_methodbuilder_from_dynamic_method (&rmb, mb);
@@ -10603,9 +11546,14 @@ mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
                rmb.refs [i + 1] = handle_class;
        }               
 
-       klass = mb->owner ? mono_class_from_mono_type (mb->owner->type) : mono_defaults.object_class;
+       klass = mb->owner ? mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)mb->owner)) : mono_defaults.object_class;
 
-       mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
+       mb->mhandle = handle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
+       release_data = g_new (DynamicMethodReleaseData, 1);
+       release_data->handle = handle;
+       release_data->domain = mono_object_get_domain ((MonoObject*)mb);
+       if (!mono_gc_reference_queue_add (queue, (MonoObject*)mb, release_data))
+               g_free (release_data);
 
        /* Fix up refs entries pointing at us */
        for (l = mb->referenced_by; l; l = l->next) {
@@ -10631,16 +11579,6 @@ mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
 
 #endif /* DISABLE_REFLECTION_EMIT */
 
-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_is_valid_dynamic_token:
@@ -10654,6 +11592,19 @@ mono_reflection_is_valid_dynamic_token (MonoDynamicImage *image, guint32 token)
        return mono_g_hash_table_lookup (image->tokens, GUINT_TO_POINTER (token)) != NULL;
 }
 
+MonoMethodSignature *
+mono_reflection_lookup_signature (MonoImage *image, MonoMethod *method, guint32 token)
+{
+       MonoMethodSignature *sig;
+       g_assert (image->dynamic);
+
+       sig = g_hash_table_lookup (((MonoDynamicImage*)image)->vararg_aux_hash, GUINT_TO_POINTER (token));
+       if (sig)
+               return sig;
+
+       return mono_method_signature (method);
+}
+
 #ifndef DISABLE_REFLECTION_EMIT
 
 /**
@@ -10678,7 +11629,7 @@ mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean
        mono_loader_unlock ();
        if (!obj) {
                if (valid_token)
-                       g_assert_not_reached ();
+                       g_error ("Could not find required dynamic token 0x%08x", token);
                else
                        return NULL;
        }
@@ -10697,8 +11648,8 @@ mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean
 static void
 ensure_complete_type (MonoClass *klass)
 {
-       if (klass->image->dynamic && !klass->wastypebuilder) {
-               MonoReflectionTypeBuilder *tb = klass->reflection_info;
+       if (klass->image->dynamic && !klass->wastypebuilder && mono_class_get_ref_info (klass)) {
+               MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
 
                mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
 
@@ -10723,16 +11674,20 @@ resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, Mon
 
        if (strcmp (obj->vtable->klass->name, "String") == 0) {
                result = mono_string_intern ((MonoString*)obj);
-               *handle_class = NULL;
+               *handle_class = mono_defaults.string_class;
                g_assert (result);
        } else if (strcmp (obj->vtable->klass->name, "MonoType") == 0) {
-               MonoReflectionType *tb = (MonoReflectionType*)obj;
+               MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
+               MonoClass *mc = mono_class_from_mono_type (type);
+               if (!mono_class_init (mc))
+                       mono_raise_exception (mono_class_get_exception_for_failure (mc));
+
                if (context) {
-                       MonoType *inflated = mono_class_inflate_generic_type (tb->type, context);
+                       MonoType *inflated = mono_class_inflate_generic_type (type, context);
                        result = mono_class_from_mono_type (inflated);
                        mono_metadata_free_type (inflated);
                } else {
-                       result = mono_class_from_mono_type (tb->type);
+                       result = mono_class_from_mono_type (type);
                }
                *handle_class = mono_defaults.typehandle_class;
                g_assert (result);
@@ -10824,16 +11779,17 @@ resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, Mon
                *handle_class = mono_defaults.fieldhandle_class;
        } else if (strcmp (obj->vtable->klass->name, "TypeBuilder") == 0) {
                MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
+               MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)tb); 
                MonoClass *klass;
 
-               klass = tb->type.type->data.klass;
+               klass = type->data.klass;
                if (klass->wastypebuilder) {
                        /* Already created */
                        result = klass;
                }
                else {
                        mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
-                       result = tb->type.type->data.klass;
+                       result = type->data.klass;
                        g_assert (result);
                }
                *handle_class = mono_defaults.typehandle_class;
@@ -10851,21 +11807,20 @@ resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, Mon
                sig->explicit_this = helper->call_conv & 64 ? 1 : 0;
                sig->hasthis = helper->call_conv & 32 ? 1 : 0;
 
-               if (helper->call_conv == 0) /* unmanaged */
+               if (helper->unmanaged_call_conv) { /* unmanaged */
                        sig->call_convention = helper->unmanaged_call_conv - 1;
-               else
-                       if (helper->call_conv & 0x02)
-                               sig->call_convention = MONO_CALL_VARARG;
-               else
+                       sig->pinvoke = TRUE;
+               } else if (helper->call_conv & 0x02) {
+                       sig->call_convention = MONO_CALL_VARARG;
+               } else {
                        sig->call_convention = MONO_CALL_DEFAULT;
+               }
 
                sig->param_count = nargs;
                /* TODO: Copy type ? */
                sig->ret = helper->return_type->type;
-               for (i = 0; i < nargs; ++i) {
-                       MonoReflectionType *rt = mono_type_array_get (helper->arguments, i);
-                       sig->params [i] = rt->type;
-               }
+               for (i = 0; i < nargs; ++i)
+                       sig->params [i] = mono_type_array_get_and_resolve (helper->arguments, i);
 
                result = sig;
                *handle_class = NULL;
@@ -10876,15 +11831,15 @@ resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, Mon
                result = method->mhandle;
                *handle_class = mono_defaults.methodhandle_class;
        } else if (strcmp (obj->vtable->klass->name, "GenericTypeParameterBuilder") == 0) {
-               MonoReflectionType *tb = (MonoReflectionType*)obj;
-               MonoType *type = mono_class_inflate_generic_type (tb->type, context);
+               MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
+               type = mono_class_inflate_generic_type (type, context);
                result = mono_class_from_mono_type (type);
                *handle_class = mono_defaults.typehandle_class;
                g_assert (result);
                mono_metadata_free_type (type);
        } else if (strcmp (obj->vtable->klass->name, "MonoGenericClass") == 0) {
-               MonoReflectionGenericClass *ref = (MonoReflectionGenericClass*)obj;
-               MonoType *type = mono_class_inflate_generic_type (ref->type.type, context);
+               MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
+               type = mono_class_inflate_generic_type (type, context);
                result = mono_class_from_mono_type (type);
                *handle_class = mono_defaults.typehandle_class;
                g_assert (result);
@@ -10893,33 +11848,97 @@ resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, Mon
                MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
                MonoClass *inflated;
                MonoType *type;
+               MonoClassField *field;
+
+               if (is_sre_field_builder (mono_object_class (f->fb)))
+                       field = ((MonoReflectionFieldBuilder*)f->fb)->handle;
+               else if (is_sr_mono_field (mono_object_class (f->fb)))
+                       field = ((MonoReflectionField*)f->fb)->field;
+               else
+                       g_error ("resolve_object:: can't handle a FTBI with base_method of type %s", mono_type_get_full_name (mono_object_class (f->fb)));
 
-               type = mono_class_inflate_generic_type (f->inst->type.type, context);
+               type = mono_class_inflate_generic_type (mono_reflection_type_get_handle ((MonoReflectionType*)f->inst), context);
                inflated = mono_class_from_mono_type (type);
 
-               g_assert (f->fb->handle);
-               result = mono_class_get_field_from_name (inflated, mono_field_get_name (f->fb->handle));
+               result = field = mono_class_get_field_from_name (inflated, mono_field_get_name (field));
+               ensure_complete_type (field->parent);
                g_assert (result);
                mono_metadata_free_type (type);
                *handle_class = mono_defaults.fieldhandle_class;
        } else if (strcmp (obj->vtable->klass->name, "ConstructorOnTypeBuilderInst") == 0) {
                MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
-               MonoType *type = mono_class_inflate_generic_type (c->inst->type.type, context);
+               MonoType *type = mono_class_inflate_generic_type (mono_reflection_type_get_handle ((MonoReflectionType*)c->inst), context);
                MonoClass *inflated_klass = mono_class_from_mono_type (type);
-               g_assert (c->cb->mhandle);
-               result = inflate_mono_method (inflated_klass, c->cb->mhandle, (MonoObject*)c->cb);
+               MonoMethod *method;
+
+               if (is_sre_ctor_builder (mono_object_class (c->cb)))
+                       method = ((MonoReflectionCtorBuilder *)c->cb)->mhandle;
+               else if (is_sr_mono_cmethod (mono_object_class (c->cb)))
+                       method = ((MonoReflectionMethod *)c->cb)->method;
+               else
+                       g_error ("resolve_object:: can't handle a CTBI with base_method of type %s", mono_type_get_full_name (mono_object_class (c->cb)));
+
+               result = inflate_mono_method (inflated_klass, method, (MonoObject*)c->cb);
                *handle_class = mono_defaults.methodhandle_class;
                mono_metadata_free_type (type);
        } else if (strcmp (obj->vtable->klass->name, "MethodOnTypeBuilderInst") == 0) {
                MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
-               MonoType *type = mono_class_inflate_generic_type (m->inst->type.type, context);
-               MonoClass *inflated_klass = mono_class_from_mono_type (type);
-               g_assert (m->mb->mhandle);
-               result = inflate_mono_method (inflated_klass, m->mb->mhandle, (MonoObject*)m->mb);
+               if (m->method_args) {
+                       result = mono_reflection_method_on_tb_inst_get_handle (m);
+                       if (context)
+                               result = mono_class_inflate_generic_method (result, context);
+               } else {
+                       MonoType *type = mono_class_inflate_generic_type (mono_reflection_type_get_handle ((MonoReflectionType*)m->inst), context);
+                       MonoClass *inflated_klass = mono_class_from_mono_type (type);
+                       MonoMethod *method;
+
+                       if (is_sre_method_builder (mono_object_class (m->mb)))
+                               method = ((MonoReflectionMethodBuilder *)m->mb)->mhandle;
+                       else if (is_sr_mono_method (mono_object_class (m->mb)))
+                               method = ((MonoReflectionMethod *)m->mb)->method;
+                       else
+                               g_error ("resolve_object:: can't handle a MTBI with base_method of type %s", mono_type_get_full_name (mono_object_class (m->mb)));
+
+                       result = inflate_mono_method (inflated_klass, method, (MonoObject*)m->mb);
+                       mono_metadata_free_type (type);
+               }
                *handle_class = mono_defaults.methodhandle_class;
-               mono_metadata_free_type (type);
+       } else if (strcmp (obj->vtable->klass->name, "MonoArrayMethod") == 0) {
+               MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod*)obj;
+               MonoType *mtype;
+               MonoClass *klass;
+               MonoMethod *method;
+               gpointer iter;
+               char *name;
+
+               mtype = mono_reflection_type_get_handle (m->parent);
+               klass = mono_class_from_mono_type (mtype);
+
+               /* Find the method */
+
+               name = mono_string_to_utf8 (m->name);
+               iter = NULL;
+               while ((method = mono_class_get_methods (klass, &iter))) {
+                       if (!strcmp (method->name, name))
+                               break;
+               }
+               g_free (name);
+
+               // FIXME:
+               g_assert (method);
+               // FIXME: Check parameters/return value etc. match
+
+               result = method;
+               *handle_class = mono_defaults.methodhandle_class;
+       } else if (is_sre_array (mono_object_get_class(obj)) ||
+                               is_sre_byref (mono_object_get_class(obj)) ||
+                               is_sre_pointer (mono_object_get_class(obj))) {
+               MonoReflectionType *ref_type = (MonoReflectionType *)obj;
+               MonoType *type = mono_reflection_type_get_handle (ref_type);
+               result = mono_class_from_mono_type (type);
+               *handle_class = mono_defaults.typehandle_class;
        } else {
-               g_print (obj->vtable->klass->name);
+               g_print ("%s\n", obj->vtable->klass->name);
                g_assert_not_reached ();
        }
        return result;
@@ -10970,6 +11989,12 @@ mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
        g_assert_not_reached ();
 }
 
+void
+mono_image_set_wrappers_type (MonoReflectionModuleBuilder *moduleb, MonoReflectionType *type)
+{
+       g_assert_not_reached ();
+}
+
 MonoReflectionModule *
 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
 {
@@ -10993,7 +12018,7 @@ mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, Mon
 
 guint32
 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj, 
-                                                gboolean create_methodspec, gboolean register_token)
+                                                gboolean create_open_instance, gboolean register_token)
 {
        g_assert_not_reached ();
        return 0;
@@ -11064,6 +12089,20 @@ mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean
        return NULL;
 }
 
+MonoType*
+mono_reflection_type_get_handle (MonoReflectionType* ref)
+{
+       if (!ref)
+               return NULL;
+       return ref->type;
+}
+
+void
+mono_reflection_free_dynamic_generic_class (MonoGenericClass *gclass)
+{
+       g_assert_not_reached ();
+}
+
 #endif /* DISABLE_REFLECTION_EMIT */
 
 /* SECURITY_ACTION_* are defined in mono/metadata/tabledefs.h */
@@ -11510,14 +12549,14 @@ mono_reflection_call_is_assignable_to (MonoClass *klass, MonoClass *oklass)
 
        /* 
         * The result of mono_type_get_object () might be a System.MonoType but we
-        * need a TypeBuilder so use klass->reflection_info.
+        * need a TypeBuilder so use mono_class_get_ref_info (klass).
         */
-       g_assert (klass->reflection_info);
-       g_assert (!strcmp (((MonoObject*)(klass->reflection_info))->vtable->klass->name, "TypeBuilder"));
+       g_assert (mono_class_get_ref_info (klass));
+       g_assert (!strcmp (((MonoObject*)(mono_class_get_ref_info (klass)))->vtable->klass->name, "TypeBuilder"));
 
        params [0] = mono_type_get_object (mono_domain_get (), &oklass->byval_arg);
 
-       res = mono_runtime_invoke (method, (MonoObject*)(klass->reflection_info), params, &exc);
+       res = mono_runtime_invoke (method, (MonoObject*)(mono_class_get_ref_info (klass)), params, &exc);
        if (exc)
                return FALSE;
        else