2003-05-14 Zoltan Varga <vargaz@freemail.hu>
[mono.git] / mono / metadata / reflection.c
index 32ee621d9ab841e7b1394e6577d006f342dbd79c..56d9719f4fb3651bc3175c7e71839f2bac112cc7 100644 (file)
@@ -49,6 +49,7 @@ typedef struct {
        MonoObject *type;
        MonoString *name;
        MonoBoolean init_locals;
+       MonoMethod *mhandle;
 } ReflectionMethodBuilder;
 
 const unsigned char table_sizes [64] = {
@@ -97,8 +98,23 @@ const unsigned char table_sizes [64] = {
        0       /* 0x2A */
 };
 
+/**
+ * These macros can be used to allocate long living atomic data so it won't be
+ * tracked by the garbage collector.
+ */
+#ifdef HAVE_BOEHM_GC
+#define ALLOC_ATOMIC(size) GC_MALLOC_ATOMIC (size)
+#define FREE_ATOMIC(ptr)
+#define REALLOC_ATOMIC(ptr, size) GC_REALLOC ((ptr), (size))
+#else
+#define ALLOC_ATOMIC(size) g_malloc (size)
+#define FREE_ATOMIC(ptr) g_free (ptr)
+#define REALLOC_ATOMIC(ptr, size) g_realloc ((ptr), (size))
+#endif
+
 static guint32 mono_image_typedef_or_ref (MonoDynamicAssembly *assembly, MonoType *type);
 static guint32 mono_image_get_methodref_token (MonoDynamicAssembly *assembly, MonoMethod *method);
+static guint32 mono_image_get_sighelper_token (MonoDynamicAssembly *assembly, MonoReflectionSigHelper *helper);
 static guint32 encode_marshal_blob (MonoDynamicAssembly *assembly, MonoReflectionMarshal *minfo);
 
 static void
@@ -106,9 +122,29 @@ alloc_table (MonoDynamicTable *table, guint nrows)
 {
        table->rows = nrows;
        g_assert (table->columns);
-       table->values = g_realloc (table->values, (1 + table->rows) * table->columns * sizeof (guint32));
+       if (nrows + 1 >= table->alloc_rows) {
+               while (nrows + 1 >= table->alloc_rows)
+                       if (table->alloc_rows == 0)
+                               table->alloc_rows = 16;
+                       else
+                               table->alloc_rows *= 2;
+
+               table->values = REALLOC_ATOMIC (table->values, (table->alloc_rows) * table->columns * sizeof (guint32));
+       }
 }
 
+static void
+make_room_in_stream (MonoDynamicStream *stream, int size)
+{
+       while (stream->alloc_size <= size) {
+               if (stream->alloc_size < 4096)
+                       stream->alloc_size = 4096;
+               else
+                       stream->alloc_size *= 2;
+       }
+       stream->data = REALLOC_ATOMIC (stream->data, stream->alloc_size);
+}      
+
 static guint32
 string_heap_insert (MonoDynamicStream *sh, const char *str)
 {
@@ -121,10 +157,9 @@ string_heap_insert (MonoDynamicStream *sh, const char *str)
 
        len = strlen (str) + 1;
        idx = sh->index;
-       if (idx + len > sh->alloc_size) {
-               sh->alloc_size += len + 4096;
-               sh->data = g_realloc (sh->data, sh->alloc_size);
-       }
+       if (idx + len > sh->alloc_size)
+               make_room_in_stream (sh, idx + len);
+
        /*
         * We strdup the string even if we already copy them in sh->data
         * so that the string pointers in the hash remain valid even if
@@ -141,7 +176,7 @@ string_heap_init (MonoDynamicStream *sh)
 {
        sh->index = 0;
        sh->alloc_size = 4096;
-       sh->data = g_malloc (4096);
+       sh->data = ALLOC_ATOMIC (4096);
        sh->hash = g_hash_table_new (g_str_hash, g_str_equal);
        string_heap_insert (sh, "");
 }
@@ -150,7 +185,7 @@ string_heap_init (MonoDynamicStream *sh)
 static void
 string_heap_free (MonoDynamicStream *sh)
 {
-       g_free (sh->data);
+       FREE_ATOMIC (sh->data);
        g_hash_table_foreach (sh->hash, (GHFunc)g_free, NULL);
        g_hash_table_destroy (sh->hash);
 }
@@ -160,10 +195,8 @@ static guint32
 mono_image_add_stream_data (MonoDynamicStream *stream, const char *data, guint32 len)
 {
        guint32 idx;
-       if (stream->alloc_size < stream->index + len) {
-               stream->alloc_size += len + 4096;
-               stream->data = g_realloc (stream->data, stream->alloc_size);
-       }
+       if (stream->alloc_size < stream->index + len)
+               make_room_in_stream (stream, stream->index + len);
        memcpy (stream->data + stream->index, data, len);
        idx = stream->index;
        stream->index += len;
@@ -178,10 +211,8 @@ static guint32
 mono_image_add_stream_zero (MonoDynamicStream *stream, guint32 len)
 {
        guint32 idx;
-       if (stream->alloc_size < stream->index + len) {
-               stream->alloc_size += len + 4096;
-               stream->data = g_realloc (stream->data, stream->alloc_size);
-       }
+       if (stream->alloc_size < stream->index + len)
+               make_room_in_stream (stream, stream->index + len);
        memset (stream->data + stream->index, 0, len);
        idx = stream->index;
        stream->index += len;
@@ -205,11 +236,15 @@ mono_blob_entry_hash (const char* str)
        guint len, h;
        const char *end;
        len = mono_metadata_decode_blob_size (str, &str);
-       end = str + len;
-       h = *str;
-       for (str += 1; str < end; str++)
-               h = (h << 5) - h + *str;
-       return h;
+       if (len > 0) {
+               end = str + len;
+               h = *str;
+               for (str += 1; str < end; str++)
+                       h = (h << 5) - h + *str;
+               return h;
+       }
+       else
+               return 0;
 }
 
 static gboolean
@@ -231,16 +266,16 @@ add_to_blob_cached (MonoDynamicAssembly *assembly, char *b1, int s1, char *b2, i
        char *copy;
        gpointer oldkey, oldval;
        
-       copy = g_malloc (s1+s2);
+       copy = ALLOC_ATOMIC (s1+s2);
        memcpy (copy, b1, s1);
        memcpy (copy + s1, b2, s2);
-       if (g_hash_table_lookup_extended (assembly->blob_cache, copy, &oldkey, &oldval)) {
-               g_free (copy);
+       if (mono_g_hash_table_lookup_extended (assembly->blob_cache, copy, &oldkey, &oldval)) {
+               FREE_ATOMIC (copy);
                idx = GPOINTER_TO_UINT (oldval);
        } else {
                idx = mono_image_add_stream_data (&assembly->blob, b1, s1);
                mono_image_add_stream_data (&assembly->blob, b2, s2);
-               g_hash_table_insert (assembly->blob_cache, copy, GUINT_TO_POINTER (idx));
+               mono_g_hash_table_insert (assembly->blob_cache, copy, GUINT_TO_POINTER (idx));
        }
        return idx;
 }
@@ -351,7 +386,10 @@ method_encode_signature (MonoDynamicAssembly *assembly, MonoMethodSignature *sig
        guint32 idx;
        char blob_size [6];
        char *b = blob_size;
-       
+
+       if (!assembly->save)
+               return 0;
+
        p = buf = g_malloc (size);
        /*
         * FIXME: vararg, explicit_this, differenc call_conv values...
@@ -478,7 +516,7 @@ method_encode_clauses (MonoDynamicAssembly *assembly,
        clauses = g_new0 (MonoExceptionClause, num_clauses);
 
        clause_index = 0;
-       for (i = 0; i < mono_array_length (ilgen->ex_handlers); ++i) {
+       for (i = mono_array_length (ilgen->ex_handlers) - 1; i >= 0; --i) {
                ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
                finally_start = ex_info->start + ex_info->len;
                g_assert (ex_info->handlers);
@@ -546,6 +584,9 @@ method_encode_code (MonoDynamicAssembly *assembly, ReflectionMethodBuilder *mb)
                        num_exception = method_count_clauses (mb->ilgen);
        } else {
                code = mb->code;
+               if (code == NULL)
+                       mono_raise_exception (mono_get_exception_argument (NULL, "a method does not have any IL associated"));
+
                code_size = mono_array_length (code);
                max_stack = 8; /* we probably need to run a verifier on the code... */
        }
@@ -662,6 +703,59 @@ find_index_in_table (MonoDynamicAssembly *assembly, int table_idx, int col, guin
        return 0;
 }
 
+static GHashTable *dynamic_custom_attrs = NULL;
+
+static MonoCustomAttrInfo*
+mono_custom_attrs_from_builders (MonoImage *image, MonoArray *cattrs)
+{
+       int i, count;
+       MonoCustomAttrInfo *ainfo;
+       MonoReflectionCustomAttr *cattr;
+
+       if (!cattrs)
+               return NULL;
+       /* FIXME: check in assembly the Run flag is set */
+
+       count = mono_array_length (cattrs);
+
+       ainfo = g_malloc0 (sizeof (MonoCustomAttrInfo) + sizeof (MonoCustomAttrEntry) * (count - MONO_ZERO_LEN_ARRAY));
+
+       ainfo->image = image;
+       ainfo->num_attrs = count;
+       for (i = 0; i < count; ++i) {
+               cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
+               ainfo->attrs [i].ctor = cattr->ctor->method;
+               /* FIXME: might want to memdup the data here */
+               ainfo->attrs [i].data = mono_array_addr (cattr->data, char, 0);
+               ainfo->attrs [i].data_size = mono_array_length (cattr->data);
+       }
+
+       return ainfo;
+}
+
+static void
+mono_save_custom_attrs (MonoImage *image, void *obj, MonoArray *cattrs)
+{
+       MonoCustomAttrInfo *ainfo = mono_custom_attrs_from_builders (image, cattrs);
+
+       if (!ainfo)
+               return;
+
+       if (!dynamic_custom_attrs)
+               dynamic_custom_attrs = g_hash_table_new (NULL, NULL);
+
+       g_hash_table_insert (dynamic_custom_attrs, obj, ainfo);
+}
+
+void
+mono_custom_attrs_free (MonoCustomAttrInfo *ainfo)
+{
+       /* they are cached, so we don't free them */
+       if (dynamic_custom_attrs && g_hash_table_lookup (dynamic_custom_attrs, ainfo))
+               return;
+       g_free (ainfo);
+}
+
 /*
  * idx is the table index of the object
  * type is one of CUSTOM_ATTR_*
@@ -728,6 +822,7 @@ mono_image_basic_method (ReflectionMethodBuilder *mb, MonoDynamicAssembly *assem
        /* room in this table is already allocated */
        table = &assembly->tables [MONO_TABLE_METHOD];
        *mb->table_idx = table->next_idx ++;
+       mono_g_hash_table_insert (assembly->method_to_table_idx, mb->mhandle, GUINT_TO_POINTER ((*mb->table_idx)));
        values = table->values + *mb->table_idx * MONO_METHOD_SIZE;
        if (mb->name) {
                name = mono_string_to_utf8 (mb->name);
@@ -735,6 +830,8 @@ mono_image_basic_method (ReflectionMethodBuilder *mb, MonoDynamicAssembly *assem
                g_free (name);
        } else { /* a constructor */
                values [MONO_METHOD_NAME] = string_heap_insert (&assembly->sheap, mb->attrs & METHOD_ATTRIBUTE_STATIC? ".cctor": ".ctor");
+               // MS.NET adds this automatically
+               mb->attrs |= METHOD_ATTRIBUTE_RT_SPECIAL_NAME;
        }
        values [MONO_METHOD_FLAGS] = mb->attrs;
        values [MONO_METHOD_IMPLFLAGS] = mb->iattrs;
@@ -805,6 +902,7 @@ mono_image_get_method_info (MonoReflectionMethodBuilder *mb, MonoDynamicAssembly
        rmb.name = mb->name;
        rmb.table_idx = &mb->table_idx;
        rmb.init_locals = mb->init_locals;
+       rmb.mhandle = mb->mhandle;
 
        mono_image_basic_method (&rmb, assembly);
 
@@ -814,7 +912,8 @@ mono_image_get_method_info (MonoReflectionMethodBuilder *mb, MonoDynamicAssembly
                table->rows ++;
                alloc_table (table, table->rows);
                values = table->values + table->rows * MONO_IMPLMAP_SIZE;
-               values [MONO_IMPLMAP_FLAGS] = (mb->native_cc << 8) | mb->charset;
+               /* map CharSet values to on-disk values */
+               values [MONO_IMPLMAP_FLAGS] = (mb->native_cc << 8) | (mb->charset ? (mb->charset - 1) * 2: 1);
                values [MONO_IMPLMAP_MEMBER] = (mb->table_idx << 1) | 1; /* memberforwarded: method */
                name = mono_string_to_utf8 (mb->dllentry);
                values [MONO_IMPLMAP_NAME] = string_heap_insert (&assembly->sheap, name);
@@ -830,6 +929,7 @@ mono_image_get_method_info (MonoReflectionMethodBuilder *mb, MonoDynamicAssembly
                        values [MONO_IMPLMAP_SCOPE] = table->rows;
                }
        }
+
        if (mb->override_method) {
                MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
                guint32 tok;
@@ -871,6 +971,7 @@ mono_image_get_ctor_info (MonoDomain *domain, MonoReflectionCtorBuilder *mb, Mon
        rmb.name = NULL;
        rmb.table_idx = &mb->table_idx;
        rmb.init_locals = mb->init_locals;
+       rmb.mhandle = mb->mhandle;
 
        mono_image_basic_method (&rmb, assembly);
 
@@ -884,7 +985,10 @@ fieldref_encode_signature (MonoDynamicAssembly *assembly, MonoClassField *field)
        char *p;
        char* buf;
        guint32 idx;
-       
+
+       if (!assembly->save)
+               return 0;
+
        p = buf = g_malloc (64);
        
        mono_metadata_encode_value (0x06, p, &p);
@@ -1025,7 +1129,7 @@ handle_enum:
                        g_free (swapped);
                }
 #else
-               idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (const char*)mono_string_chars (str), len);
+               idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
 #endif
 
                g_free (buf);
@@ -1059,7 +1163,12 @@ encode_marshal_blob (MonoDynamicAssembly *assembly, MonoReflectionMarshal *minfo
        p = buf = g_malloc (256);
 
        switch (minfo->type) {
-       /* FIXME: handle ARRAY and other unmanaged types that need extra info */
+       case MONO_NATIVE_BYVALTSTR:
+       case MONO_NATIVE_BYVALARRAY:
+               mono_metadata_encode_value (minfo->type, p, &p);
+               mono_metadata_encode_value (minfo->count, p, &p);
+               break;
+               /* FIXME: handle ARRAY and other unmanaged types that need extra info */
        default:
                mono_metadata_encode_value (minfo->type, p, &p);
                break;
@@ -1083,6 +1192,7 @@ mono_image_get_field_info (MonoReflectionFieldBuilder *fb, MonoDynamicAssembly *
                fb->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
        table = &assembly->tables [MONO_TABLE_FIELD];
        fb->table_idx = table->next_idx ++;
+       mono_g_hash_table_insert (assembly->field_to_table_idx, fb->handle, GUINT_TO_POINTER (fb->table_idx));
        values = table->values + fb->table_idx * MONO_FIELD_SIZE;
        name = mono_string_to_utf8 (fb->name);
        values [MONO_FIELD_NAME] = string_heap_insert (&assembly->sheap, name);
@@ -1375,15 +1485,16 @@ create_typespec (MonoDynamicAssembly *assembly, MonoType *type)
        default:
                return 0;
        }
-       
-       g_assert (p-sig < 128);
-       mono_metadata_encode_value (p-sig, b, &b);
-       token = add_to_blob_cached (assembly, blob_size, b-blob_size, sig, p-sig);
 
        table = &assembly->tables [MONO_TABLE_TYPESPEC];
-       alloc_table (table, table->rows + 1);
-       values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
-       values [MONO_TYPESPEC_SIGNATURE] = token;
+       if (assembly->save) {
+               g_assert (p-sig < 128);
+               mono_metadata_encode_value (p-sig, b, &b);
+               token = add_to_blob_cached (assembly, blob_size, b-blob_size, sig, p-sig);
+               alloc_table (table, table->rows + 1);
+               values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
+               values [MONO_TYPESPEC_SIGNATURE] = token;
+       }
 
        token = TYPEDEFORREF_TYPESPEC | (table->next_idx << TYPEDEFORREF_BITS);
        g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
@@ -1395,8 +1506,7 @@ create_typespec (MonoDynamicAssembly *assembly, MonoType *type)
  * Despite the name, we handle also TypeSpec (with the above helper).
  */
 static guint32
-mono_image_typedef_or_ref_aux (MonoDynamicAssembly *assembly, MonoType *type,
-                                                          gboolean force_ref)
+mono_image_typedef_or_ref (MonoDynamicAssembly *assembly, MonoType *type)
 {
        MonoDynamicTable *table;
        guint32 *values;
@@ -1418,10 +1528,11 @@ mono_image_typedef_or_ref_aux (MonoDynamicAssembly *assembly, MonoType *type,
        klass = my_mono_class_from_mono_type (type);
        if (!klass)
                klass = mono_class_from_mono_type (type);
+
        /*
         * If it's in the same module:
         */
-       if (!force_ref && (klass->image == assembly->assembly.image)) {
+       if (klass->image == assembly->assembly.image) {
                MonoReflectionTypeBuilder *tb = klass->reflection_info;
                token = TYPEDEFORREF_TYPEDEF | (tb->table_idx << TYPEDEFORREF_BITS);
                mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), klass);
@@ -1437,11 +1548,13 @@ mono_image_typedef_or_ref_aux (MonoDynamicAssembly *assembly, MonoType *type,
                scope = resolution_scope_from_image (assembly, klass->image);
        }
        table = &assembly->tables [MONO_TABLE_TYPEREF];
-       alloc_table (table, table->rows + 1);
-       values = table->values + table->next_idx * MONO_TYPEREF_SIZE;
-       values [MONO_TYPEREF_SCOPE] = scope;
-       values [MONO_TYPEREF_NAME] = string_heap_insert (&assembly->sheap, klass->name);
-       values [MONO_TYPEREF_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
+       if (assembly->save) {
+               alloc_table (table, table->rows + 1);
+               values = table->values + table->next_idx * MONO_TYPEREF_SIZE;
+               values [MONO_TYPEREF_SCOPE] = scope;
+               values [MONO_TYPEREF_NAME] = string_heap_insert (&assembly->sheap, klass->name);
+               values [MONO_TYPEREF_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
+       }
        token = TYPEDEFORREF_TYPEREF | (table->next_idx << TYPEDEFORREF_BITS); /* typeref */
        g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
        table->next_idx ++;
@@ -1449,12 +1562,6 @@ mono_image_typedef_or_ref_aux (MonoDynamicAssembly *assembly, MonoType *type,
        return token;
 }
 
-static guint32
-mono_image_typedef_or_ref (MonoDynamicAssembly *assembly, MonoType *type)
-{
-       return mono_image_typedef_or_ref_aux (assembly, type, FALSE);
-}
-
 /*
  * 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
@@ -1469,7 +1576,7 @@ mono_image_get_memberref_token (MonoDynamicAssembly *assembly, MonoType *type, c
        guint32 token, pclass;
        guint32 parent;
 
-       parent = mono_image_typedef_or_ref_aux (assembly, type, TRUE);
+       parent = mono_image_typedef_or_ref (assembly, type);
        switch (parent & TYPEDEFORREF_MASK) {
        case TYPEDEFORREF_TYPEREF:
                pclass = MEMBERREF_PARENT_TYPEREF;
@@ -1487,11 +1594,15 @@ mono_image_get_memberref_token (MonoDynamicAssembly *assembly, MonoType *type, c
        parent >>= TYPEDEFORREF_BITS;
 
        table = &assembly->tables [MONO_TABLE_MEMBERREF];
-       alloc_table (table, table->rows + 1);
-       values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
-       values [MONO_MEMBERREF_CLASS] = pclass | (parent << MEMBERREF_PARENT_BITS);
-       values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
-       values [MONO_MEMBERREF_SIGNATURE] = sig;
+
+       if (assembly->save) {
+               alloc_table (table, table->rows + 1);
+               values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
+               values [MONO_MEMBERREF_CLASS] = pclass | (parent << MEMBERREF_PARENT_BITS);
+               values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
+               values [MONO_MEMBERREF_SIGNATURE] = sig;
+       }
+
        token = MONO_TOKEN_MEMBER_REF | table->next_idx;
        table->next_idx ++;
 
@@ -1527,6 +1638,84 @@ mono_image_get_fieldref_token (MonoDynamicAssembly *assembly, MonoClassField *fi
        return token;
 }
 
+static guint32
+mono_reflection_encode_sighelper (MonoDynamicAssembly *assembly, MonoReflectionSigHelper *helper)
+{
+       char *buf;
+       char *p;
+       guint32 nargs;
+       guint32 size;
+       guint32 i, idx;
+       char blob_size [6];
+       char *b = blob_size;
+
+       if (!assembly->save)
+               return 0;
+
+       /* FIXME: */
+       g_assert (helper->type == 2);
+
+       if (helper->arguments)
+               nargs = mono_array_length (helper->arguments);
+       else
+               nargs = 0;
+
+       size = 10 + (nargs * 10);
+       
+       p = buf = g_malloc (size);
+
+       /* Encode calling convention */
+       /* Change Any to Standard */
+       if ((helper->call_conv & 0x03) == 0x03)
+               helper->call_conv = 0x01;
+       /* explicit_this implies has_this */
+       if (helper->call_conv & 0x40)
+               helper->call_conv &= 0x20;
+
+       if (helper->call_conv == 0) /* Unmanaged */
+               *p = helper->unmanaged_call_conv - 1;
+       else {
+               /* Managed */
+               *p = helper->call_conv & 0x60; /* has_this + explicit_this */
+               if (helper->call_conv & 0x02) /* varargs */
+                       *p += 0x05;
+       }
+
+       p++;
+       mono_metadata_encode_value (nargs, p, &p);
+       encode_reflection_type (assembly, helper->return_type, p, &p);
+       for (i = 0; i < nargs; ++i) {
+               MonoReflectionType *pt = mono_array_get (helper->arguments, MonoReflectionType*, i);
+               encode_reflection_type (assembly, pt, p, &p);
+       }
+       /* store length */
+       g_assert (p - buf < size);
+       mono_metadata_encode_value (p-buf, b, &b);
+       idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
+       g_free (buf);
+
+       return idx;
+}
+       
+static guint32 
+mono_image_get_sighelper_token (MonoDynamicAssembly *assembly, MonoReflectionSigHelper *helper)
+{
+       guint32 idx;
+       MonoDynamicTable *table;
+       guint32 *values;
+
+       table = &assembly->tables [MONO_TABLE_STANDALONESIG];
+       idx = table->next_idx ++;
+       table->rows ++;
+       alloc_table (table, table->rows);
+       values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
+
+       values [MONO_STAND_ALONE_SIGNATURE] =
+               mono_reflection_encode_sighelper (assembly, helper);
+
+       return idx;
+}
+
 static int
 reflection_cc_to_file (int call_conv) {
        switch (call_conv & 0x3) {
@@ -1574,6 +1763,7 @@ mono_image_get_array_token (MonoDynamicAssembly *assembly, MonoReflectionArrayMe
                                mono_metadata_signature_equal (am->sig, sig)) {
                        g_free (name);
                        g_free (sig);
+                       m->table_idx = am->token & 0xffffff;
                        return am->token;
                }
        }
@@ -1582,7 +1772,7 @@ mono_image_get_array_token (MonoDynamicAssembly *assembly, MonoReflectionArrayMe
        am->sig = sig;
        am->parent = m->parent->type;
        am->token = mono_image_get_memberref_token (assembly, am->parent,
-               name,  method_encode_signature (assembly, sig));
+                       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;
@@ -1712,10 +1902,6 @@ mono_image_get_type_info (MonoDomain *domain, MonoReflectionTypeBuilder *tb, Mon
        if (tb->subtypes) {
                MonoDynamicTable *ntable;
                
-               table = &assembly->tables [MONO_TABLE_TYPEDEF];
-               table->rows += mono_array_length (tb->subtypes);
-               alloc_table (table, table->rows);
-
                ntable = &assembly->tables [MONO_TABLE_NESTEDCLASS];
                ntable->rows += mono_array_length (tb->subtypes);
                alloc_table (ntable, ntable->rows);
@@ -1733,28 +1919,38 @@ mono_image_get_type_info (MonoDomain *domain, MonoReflectionTypeBuilder *tb, Mon
                        values += MONO_NESTED_CLASS_SIZE;
                        ntable->next_idx++;
                }
-               for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
-                       MonoReflectionTypeBuilder *subtype = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
-
-                       mono_image_get_type_info (domain, subtype, assembly);
-               }
        }
 }
 
 static void
-assign_type_idx (MonoReflectionTypeBuilder *type, MonoDynamicTable *table)
+collect_types (GPtrArray *types, MonoReflectionTypeBuilder *type)
 {
-       int j;
+       int i;
+
+       g_ptr_array_add (types, type);
 
-       type->table_idx = table->next_idx ++;
        if (!type->subtypes)
                return;
-       for (j = 0; j < mono_array_length (type->subtypes); ++j) {
-               MonoReflectionTypeBuilder *subtype = mono_array_get (type->subtypes, MonoReflectionTypeBuilder*, j);
-               assign_type_idx (subtype, table);
+
+       for (i = 0; i < mono_array_length (type->subtypes); ++i) {
+               MonoReflectionTypeBuilder *subtype = mono_array_get (type->subtypes, MonoReflectionTypeBuilder*, i);
+               collect_types (types, subtype);
        }
 }
 
+static gint
+compare_types_by_table_idx (MonoReflectionTypeBuilder **type1, 
+                                                       MonoReflectionTypeBuilder **type2)
+{
+       if ((*type1)->table_idx < (*type2)->table_idx)
+               return -1;
+       else
+               if ((*type1)->table_idx > (*type2)->table_idx)
+                       return 1;
+       else
+               return 0;
+}
+
 static void
 params_add_cattrs (MonoDynamicAssembly *assembly, MonoArray *pinfo) {
        int i;
@@ -1852,27 +2048,6 @@ mono_image_fill_module_table (MonoDomain *domain, MonoReflectionModuleBuilder *m
        table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_MVID] = i;
        table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENC] = 0;
        table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENCBASE] = 0;
-
-       /* no types in the module */
-       if (!mb->types)
-               return;
-       
-       /*
-        * fill-in info in other tables as well.
-        */
-       table = &assembly->tables [MONO_TABLE_TYPEDEF];
-       table->rows += mono_array_length (mb->types);
-       alloc_table (table, table->rows);
-       /*
-        * We assign here the typedef indexes to avoid mismatches if a type that
-        * has not yet been stored in the tables is referenced by another type.
-        */
-       for (i = 0; i < mono_array_length (mb->types); ++i) {
-               MonoReflectionTypeBuilder *type = mono_array_get (mb->types, MonoReflectionTypeBuilder*, i);
-               assign_type_idx (type, table);
-       }
-       for (i = 0; i < mono_array_length (mb->types); ++i)
-               mono_image_get_type_info (domain, mono_array_get (mb->types, MonoReflectionTypeBuilder*, i), assembly);
 }
 
 #define align_pointer(base,p)\
@@ -2141,6 +2316,7 @@ fixup_method (MonoReflectionILGen *ilgen, gpointer value, MonoDynamicAssembly *a
        MonoReflectionCtorBuilder *ctor;
        MonoReflectionMethodBuilder *method;
        MonoReflectionTypeBuilder *tb;
+       MonoReflectionArrayMethod *am;
        guint32 i, idx;
        unsigned char *target;
 
@@ -2149,10 +2325,15 @@ fixup_method (MonoReflectionILGen *ilgen, gpointer value, MonoDynamicAssembly *a
                target = assembly->code.data + code_idx + iltoken->code_pos;
                switch (target [3]) {
                case MONO_TABLE_FIELD:
-                       if (strcmp (iltoken->member->vtable->klass->name, "FieldBuilder"))
+                       if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
+                               field = (MonoReflectionFieldBuilder *)iltoken->member;
+                               idx = field->table_idx;
+                       } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
+                               MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
+                               idx = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->field_to_table_idx, f));
+                       } else {
                                g_assert_not_reached ();
-                       field = (MonoReflectionFieldBuilder *)iltoken->member;
-                       idx = field->table_idx;
+                       }
                        break;
                case MONO_TABLE_METHOD:
                        if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
@@ -2161,6 +2342,9 @@ fixup_method (MonoReflectionILGen *ilgen, gpointer value, MonoDynamicAssembly *a
                        } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
                                ctor = (MonoReflectionCtorBuilder *)iltoken->member;
                                idx = ctor->table_idx;
+                       } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod")) {
+                               MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
+                               idx = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->method_to_table_idx, m));
                        } else {
                                g_assert_not_reached ();
                        }
@@ -2171,6 +2355,12 @@ fixup_method (MonoReflectionILGen *ilgen, gpointer value, MonoDynamicAssembly *a
                        tb = (MonoReflectionTypeBuilder *)iltoken->member;
                        idx = tb->table_idx;
                        break;
+               case MONO_TABLE_MEMBERREF:
+                       if (strcmp (iltoken->member->vtable->klass->name, "MonoArrayMethod"))
+                               g_assert_not_reached ();
+                       am = (MonoReflectionArrayMethod*)iltoken->member;
+                       idx = am->table_idx;
+                       break;
                default:
                        g_error ("got unexpected table 0x%02x in fixup", target [3]);
                }
@@ -2297,7 +2487,7 @@ load_public_key (MonoString *fname, MonoDynamicAssembly *assembly) {
  * At the end of the process, method and field tokens are fixed up and the on-disk
  * compressed metadata representation is created.
  */
-static void
+void
 mono_image_build_metadata (MonoReflectionAssemblyBuilder *assemblyb)
 {
        MonoDynamicTable *table;
@@ -2307,7 +2497,10 @@ mono_image_build_metadata (MonoReflectionAssemblyBuilder *assemblyb)
        guint32 *values;
        char *name;
        int i;
-       
+
+       if (assembly->text_rva)
+               return;
+
        assembly->text_rva = START_TEXT_RVA;
 
        table = &assembly->tables [MONO_TABLE_ASSEMBLY];
@@ -2373,6 +2566,34 @@ mono_image_build_metadata (MonoReflectionAssemblyBuilder *assemblyb)
                table->next_idx ++;
        }
 
+       /* Emit types */
+       if (assemblyb->modules) {
+               /* Collect all types into a list sorted by their table_idx */
+               GPtrArray *types = g_ptr_array_new ();
+
+               len = mono_array_length (assemblyb->modules);
+               for (i = 0; i < len; ++i) {
+                       MonoReflectionModuleBuilder *mb =
+                               mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
+                       if (mb->types)
+                               for (i = 0; i < mono_array_length (mb->types); ++i) {
+                                       MonoReflectionTypeBuilder *type = mono_array_get (mb->types, MonoReflectionTypeBuilder*, i);
+                                       collect_types (types, type);
+                               }
+               }
+
+               g_ptr_array_sort (types, (GCompareFunc)compare_types_by_table_idx);
+               table = &assembly->tables [MONO_TABLE_TYPEDEF];
+               table->rows += types->len;
+               alloc_table (table, table->rows);
+               
+               for (i = 0; i < types->len; ++i) {
+                       MonoReflectionTypeBuilder *type = g_ptr_array_index (types, i);
+                       mono_image_get_type_info (domain, type, assembly);
+               }
+               g_ptr_array_free (types, TRUE);
+       }
+
        /* 
         * table->rows is already set above and in mono_image_fill_module_table.
         */
@@ -2385,16 +2606,8 @@ mono_image_build_metadata (MonoReflectionAssemblyBuilder *assemblyb)
                        module_add_cattrs (assembly, mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i));
        }
 
-       if (assemblyb->resources) {
-               len = mono_array_length (assemblyb->resources);
-               for (i = 0; i < len; ++i)
-                       assembly_add_resource (assembly, (MonoReflectionResource*)mono_array_addr (assemblyb->resources, MonoReflectionResource, i));
-       }
-       
        /* fixup tokens */
        mono_g_hash_table_foreach (assembly->token_fixups, (GHFunc)fixup_method, assembly);
-       
-       build_compressed_metadata (assembly);
 }
 
 /*
@@ -2415,8 +2628,10 @@ mono_image_insert_string (MonoReflectionAssemblyBuilder *assembly, MonoString *s
 
        if (!assembly->dynamic_assembly)
                mono_image_basic_init (assembly);
-       mono_metadata_encode_value (1 | (str->length * 2), b, &b);
-       idx = mono_image_add_stream_data (&assembly->dynamic_assembly->us, buf, b-buf);
+
+       if (assembly->dynamic_assembly->save) {
+               mono_metadata_encode_value (1 | (str->length * 2), b, &b);
+               idx = mono_image_add_stream_data (&assembly->dynamic_assembly->us, buf, b-buf);
 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
        {
                char *swapped = g_malloc (2 * mono_string_length (str));
@@ -2430,6 +2645,9 @@ mono_image_insert_string (MonoReflectionAssemblyBuilder *assembly, MonoString *s
        mono_image_add_stream_data (&assembly->dynamic_assembly->us, (const char*)mono_string_chars (str), str->length * 2);
 #endif
        mono_image_add_stream_data (&assembly->dynamic_assembly->us, "", 1);
+       }
+       else
+               idx = assembly->dynamic_assembly->us.index ++;
 
        mono_g_hash_table_insert (assembly->dynamic_assembly->tokens, 
                                                          GUINT_TO_POINTER (MONO_TOKEN_STRING | idx), str);
@@ -2459,9 +2677,6 @@ mono_image_create_token (MonoDynamicAssembly *assembly, MonoObject *obj)
        MonoClass *klass;
        guint32 token;
 
-       if (!obj)
-               g_error ("System.Array methods not yet supported");
-       
        klass = obj->vtable->klass;
        if (strcmp (klass->name, "MethodBuilder") == 0) {
                MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
@@ -2489,20 +2704,39 @@ mono_image_create_token (MonoDynamicAssembly *assembly, MonoObject *obj)
        else if (strcmp (klass->name, "MonoCMethod") == 0 ||
                        strcmp (klass->name, "MonoMethod") == 0) {
                MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
-               token = mono_image_get_methodref_token (assembly, m->method);
+               if (m->method->klass->image == assembly->assembly.image) {
+                       static guint32 method_table_idx = 0xffffff;
+                       /*
+                        * Each token should have a unique index, but the indexes are
+                        * assigned by managed code, so we don't know about them. An
+                        * easy solution is to count backwards...
+                        */
+                       method_table_idx --;
+                       token = MONO_TOKEN_METHOD_DEF | method_table_idx;
+               } else
+                       token = mono_image_get_methodref_token (assembly, m->method);
                /*g_print ("got token 0x%08x for %s\n", token, m->method->name);*/
        }
        else if (strcmp (klass->name, "MonoField") == 0) {
                MonoReflectionField *f = (MonoReflectionField *)obj;
-               token = mono_image_get_fieldref_token (assembly, f->field, f->klass);
+               if (f->klass->image == assembly->assembly.image) {
+                       static guint32 field_table_idx = 0xffffff;
+                       field_table_idx --;
+                       token = MONO_TOKEN_FIELD_DEF | field_table_idx;
+               } else
+                       token = mono_image_get_fieldref_token (assembly, f->field, f->klass);
                /*g_print ("got token 0x%08x for %s\n", token, f->field->name);*/
        }
        else if (strcmp (klass->name, "MonoArrayMethod") == 0) {
                MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod *)obj;
                token = mono_image_get_array_token (assembly, m);
        }
+       else if (strcmp (klass->name, "SignatureHelper") == 0) {
+               MonoReflectionSigHelper *s = (MonoReflectionSigHelper*)obj;
+               token = MONO_TOKEN_SIGNATURE | mono_image_get_sighelper_token (assembly, s);
+       }
        else
-               g_print ("requested token for %s\n", klass->name);
+               g_error ("requested token for %s\n", klass->name);
 
        mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token),
                                                          obj);
@@ -2523,6 +2757,46 @@ typedef struct {
        guint32 flags;
 } MonoILT;
 
+static void register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly);
+
+static MonoImage*
+create_dynamic_mono_image (char *assembly_name, char *module_name)
+{
+       MonoImage *image;
+
+       image = g_new0 (MonoImage, 1);
+       
+       /* keep in sync with image.c */
+       image->name = assembly_name;
+       image->assembly_name = image->name; /* they may be different */
+       image->module_name = module_name;
+       image->references = g_new0 (MonoAssembly*, 1);
+       image->references [0] = NULL;
+
+       image->method_cache = g_hash_table_new (g_direct_hash, g_direct_equal);
+       image->class_cache = g_hash_table_new (g_direct_hash, g_direct_equal);
+       image->name_cache = g_hash_table_new (g_str_hash, g_str_equal);
+       image->array_cache = g_hash_table_new (g_direct_hash, g_direct_equal);
+
+       image->delegate_begin_invoke_cache = 
+               g_hash_table_new ((GHashFunc)mono_signature_hash, 
+                                 (GCompareFunc)mono_metadata_signature_equal);
+       image->delegate_end_invoke_cache = 
+               g_hash_table_new ((GHashFunc)mono_signature_hash, 
+                                 (GCompareFunc)mono_metadata_signature_equal);
+       image->delegate_invoke_cache = 
+               g_hash_table_new ((GHashFunc)mono_signature_hash, 
+                                 (GCompareFunc)mono_metadata_signature_equal);
+
+       image->runtime_invoke_cache = g_hash_table_new (g_direct_hash, g_direct_equal);
+       image->managed_wrapper_cache = g_hash_table_new (g_direct_hash, g_direct_equal);
+       image->native_wrapper_cache = g_hash_table_new (g_direct_hash, g_direct_equal);
+       image->remoting_invoke_cache = g_hash_table_new (g_direct_hash, g_direct_equal);
+       image->synchronized_cache = g_hash_table_new (g_direct_hash, g_direct_equal);
+
+       return image;
+}
+
 /*
  * mono_image_basic_init:
  * @assembly: an assembly builder object
@@ -2552,14 +2826,16 @@ mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
        assembly->assembly.dynamic = assembly;
        assemblyb->assembly.assembly = (MonoAssembly*)assembly;
        assembly->token_fixups = mono_g_hash_table_new (g_direct_hash, g_direct_equal);
+       assembly->method_to_table_idx = mono_g_hash_table_new (g_direct_hash, g_direct_equal);
+       assembly->field_to_table_idx = mono_g_hash_table_new (g_direct_hash, g_direct_equal);
        assembly->handleref = g_hash_table_new (g_direct_hash, g_direct_equal);
        assembly->tokens = mono_g_hash_table_new (g_direct_hash, g_direct_equal);
        assembly->typeref = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
-       assembly->blob_cache = g_hash_table_new ((GHashFunc)mono_blob_entry_hash, (GCompareFunc)mono_blob_entry_equal);
+       assembly->blob_cache = mono_g_hash_table_new ((GHashFunc)mono_blob_entry_hash, (GCompareFunc)mono_blob_entry_equal);
 
        string_heap_init (&assembly->sheap);
        mono_image_add_stream_data (&assembly->us, "", 1);
-       add_to_blob_cached (assembly, "", 1, NULL, 0);
+       add_to_blob_cached (assembly, (char*) "", 1, NULL, 0);
        /* import tables... */
        mono_image_add_stream_data (&assembly->code, entrycode, sizeof (entrycode));
        assembly->iat_offset = mono_image_add_stream_zero (&assembly->code, 8); /* two IAT entries */
@@ -2577,37 +2853,15 @@ mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
                assembly->tables [i].columns = table_sizes [i];
        }
 
-       image = g_new0 (MonoImage, 1);
-       
-       /* keep in sync with image.c */
-       assembly->assembly.aname.name = image->name = mono_string_to_utf8 (assemblyb->name);
-       image->assembly_name = image->name; /* they may be different */
-       image->module_name = g_strdup ("RefEmit_YouForgotToDefineAModule");
-       image->assembly = (MonoAssembly*)assembly;
-       image->references = g_new0 (MonoAssembly*, 1);
-       image->references [0] = NULL;
-
-       image->method_cache = g_hash_table_new (g_direct_hash, g_direct_equal);
-       image->class_cache = g_hash_table_new (g_direct_hash, g_direct_equal);
-       image->name_cache = g_hash_table_new (g_str_hash, g_str_equal);
-       image->array_cache = g_hash_table_new (g_direct_hash, g_direct_equal);
-
-       image->delegate_begin_invoke_cache = 
-               g_hash_table_new ((GHashFunc)mono_signature_hash, 
-                                 (GCompareFunc)mono_metadata_signature_equal);
-       image->delegate_end_invoke_cache = 
-               g_hash_table_new ((GHashFunc)mono_signature_hash, 
-                                 (GCompareFunc)mono_metadata_signature_equal);
-       image->delegate_invoke_cache = 
-               g_hash_table_new ((GHashFunc)mono_signature_hash, 
-                                 (GCompareFunc)mono_metadata_signature_equal);
+       assembly->run = assemblyb->access != 2;
+       assembly->save = assemblyb->access != 1;
 
-       image->runtime_invoke_cache = g_hash_table_new (g_direct_hash, g_direct_equal);
-       image->managed_wrapper_cache = g_hash_table_new (g_direct_hash, g_direct_equal);
-       image->native_wrapper_cache = g_hash_table_new (g_direct_hash, g_direct_equal);
-       image->remoting_invoke_cache = g_hash_table_new (g_direct_hash, g_direct_equal);
+       image = create_dynamic_mono_image (mono_string_to_utf8 (assemblyb->name), g_strdup ("RefEmit_YouForgotToDefineAModule"));
+       assembly->assembly.aname.name = image->name;
+       image->assembly = (MonoAssembly*)assembly;
        assembly->assembly.image = image;
 
+       register_assembly (mono_object_domain (assemblyb), &assemblyb->assembly, &assembly->assembly);
        mono_assembly_invoke_load_hook ((MonoAssembly*)assembly);
 }
 
@@ -2677,12 +2931,22 @@ mono_image_create_pefile (MonoReflectionAssemblyBuilder *assemblyb) {
                return;
        
        mono_image_build_metadata (assemblyb);
-       nsections = calc_section_size (assembly);
 
-       pefile = &assembly->pefile;
-
-       /* The DOS header and stub */
-       g_assert (sizeof (MonoMSDOSHeader) == sizeof (msheader));
+       if (assemblyb->resources) {
+               int len = mono_array_length (assemblyb->resources);
+               for (i = 0; i < len; ++i)
+                       assembly_add_resource (assembly, (MonoReflectionResource*)mono_array_addr (assemblyb->resources, MonoReflectionResource, i));
+       }
+
+       
+       build_compressed_metadata (assembly);
+
+       nsections = calc_section_size (assembly);
+
+       pefile = &assembly->pefile;
+
+       /* The DOS header and stub */
+       g_assert (sizeof (MonoMSDOSHeader) == sizeof (msheader));
        mono_image_add_stream_data (pefile, msheader, sizeof (msheader));
 
        /* the dotnet header */
@@ -2892,6 +3156,8 @@ mono_image_create_pefile (MonoReflectionAssemblyBuilder *assemblyb) {
                        memcpy (pefile->data + text_offset, assembly->assembly.image->raw_metadata, assembly->meta_size);
                        text_offset += assembly->meta_size;
                        memcpy (pefile->data + text_offset, assembly->strong_name, assembly->strong_name_size);
+
+                       g_free (assembly->assembly.image->raw_metadata);
                        break;
                case MONO_SECTION_RELOC:
                        rva = (guint32*)(pefile->data + assembly->sections [i].offset);
@@ -2981,6 +3247,39 @@ reflected_hash (gconstpointer a) {
                mono_domain_unlock (domain);    \
        } while (0)
 
+static void 
+register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly)
+{
+       /* this is done only once */
+       mono_domain_lock (domain);
+       CACHE_OBJECT (assembly, res, NULL);
+}
+
+static void
+register_module (MonoDomain *domain, MonoReflectionModuleBuilder *res, MonoImage *module)
+{
+       /* this is done only once */
+       mono_domain_lock (domain);
+       CACHE_OBJECT (module, res, NULL);
+}
+
+void
+mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
+{
+       MonoImage *image = moduleb->module.image;
+       MonoReflectionAssemblyBuilder *ab = moduleb->assemblyb;
+       if (!image) {
+               if (!ab->modules) {
+                       /* a MonoImage was already created in mono_image_basic_init () */
+                       image = ab->dynamic_assembly->assembly.image;
+               } else {
+                       image = create_dynamic_mono_image (mono_string_to_utf8 (ab->name), mono_string_to_utf8 (moduleb->module.name));
+               }
+               moduleb->module.image = image;
+               register_module (mono_object_domain (moduleb), moduleb, image);
+       }
+}
+
 /*
  * mono_assembly_get_object:
  * @domain: an app domain
@@ -3054,12 +3353,24 @@ mymono_metadata_type_equal (MonoType *t1, MonoType *t2)
        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:
                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_SZARRAY:
+retry_sz:
+               if (t1->data.type->type != t2->data.type->type)
+                       return FALSE;
+               if (t1->data.type->type == MONO_TYPE_CLASS || t1->data.type->type == MONO_TYPE_VALUETYPE)
+                       return t1->data.type->data.klass == t2->data.type->data.klass;
+               if (t1->data.type->type == MONO_TYPE_SZARRAY) {
+                       t1 = t1->data.type;
+                       t2 = t2->data.type;
+                       goto retry_sz;
+               }
                return mymono_metadata_type_equal (t1->data.type, t2->data.type);
        case MONO_TYPE_ARRAY:
                if (t1->data.array->rank != t2->data.array->rank)
@@ -3085,10 +3396,10 @@ mymono_metadata_type_hash (MonoType *t1)
        case MONO_TYPE_VALUETYPE:
        case MONO_TYPE_CLASS:
                /* check if the distribution is good enough */
-               return hash << 7 | g_str_hash (t1->data.klass->name);
+               return ((hash << 5) - hash) ^ g_str_hash (t1->data.klass->name);
        case MONO_TYPE_PTR:
        case MONO_TYPE_SZARRAY:
-               return hash << 7 | mymono_metadata_type_hash (t1->data.type);
+               return ((hash << 5) - hash) ^ mymono_metadata_type_hash (t1->data.type);
        }
        return hash;
 }
@@ -3259,14 +3570,15 @@ mono_param_get_objects (MonoDomain *domain, MonoMethod *method)
        if (!method->signature->param_count)
                return NULL;
 
-       member = mono_method_get_object (domain, method, NULL);
-       names = g_new (char *, method->signature->param_count);
-       mono_method_get_param_names (method, (const char **) names);
-       
        /* Note: the cache is based on the address of the signature into the method
         * since we already cache MethodInfos with the method as keys.
         */
        CHECK_OBJECT (MonoReflectionParameter**, &(method->signature), NULL);
+
+       member = mono_method_get_object (domain, method, NULL);
+       names = g_new (char *, method->signature->param_count);
+       mono_method_get_param_names (method, (const char **) names);
+       
        oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "ParameterInfo");
 #if HAVE_BOEHM_GC
        res = GC_MALLOC (sizeof (MonoReflectionParameter*) * method->signature->param_count);
@@ -3296,7 +3608,7 @@ assembly_name_to_aname (MonoAssemblyName *assembly, char *p) {
        assembly->name = p;
        assembly->culture = "";
        
-       while (*p && (isalnum (*p) || *p == '.'))
+       while (*p && (isalnum (*p) || *p == '.' || *p == '-'))
                p++;
        found_sep = 0;
        while (*p == ' ' || *p == ',') {
@@ -3357,7 +3669,8 @@ assembly_name_to_aname (MonoAssemblyName *assembly, char *p) {
                        }
                        p = s;
                } else {
-                       return 1;
+                       while (*p && *p != ',')
+                               p++;
                }
                found_sep = 0;
                while (*p == ' ' || *p == ',') {
@@ -3406,11 +3719,10 @@ mono_reflection_parse_type (char *name, MonoTypeNameParse *info) {
                case '+':
                        *p = 0; /* NULL terminate the name */
                        startn = p + 1;
+                       info->nested = g_list_append (info->nested, startn);
                        /* we have parsed the nesting namespace + name */
-                       if (info->name) {
-                               info->nested = g_list_append (info->nested, startn);
+                       if (info->name)
                                break;
-                       }
                        if (last_point) {
                                info->name_space = start;
                                *last_point = 0;
@@ -3440,9 +3752,7 @@ mono_reflection_parse_type (char *name, MonoTypeNameParse *info) {
                *w++ = *p++;
        }
        
-       if (info->name) {
-               info->nested = g_list_append (info->nested, startn);
-       } else {
+       if (!info->name) {
                if (last_point) {
                        info->name_space = start;
                        *last_point = 0;
@@ -3566,17 +3876,8 @@ mono_type_get_name (MonoType *type)
        return g_string_free (result, FALSE);
 }
 
-/*
- * mono_reflection_get_type:
- * @image: a metadata context
- * @info: type description structure
- * @ignorecase: flag for case-insensitive string compares
- *
- * Build a MonoType from the type description in @info.
- * 
- */
-MonoType*
-mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase)
+static MonoType*
+mono_reflection_get_type_internal (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase)
 {
        MonoClass *klass;
        GList *mod;
@@ -3626,9 +3927,53 @@ mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ig
                }
                mono_class_init (klass);
        }
+
        return &klass->byval_arg;
 }
 
+/*
+ * mono_reflection_get_type:
+ * @image: a metadata context
+ * @info: type description structure
+ * @ignorecase: flag for case-insensitive string compares
+ *
+ * Build a MonoType from the type description in @info.
+ * 
+ */
+
+MonoType*
+mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase)
+{
+       MonoType *type;
+       MonoReflectionAssembly *assembly;
+       GString *fullName;
+       GList *mod;
+
+       type = mono_reflection_get_type_internal (image, info, ignorecase);
+       if (type)
+               return type;
+       if (!mono_domain_has_type_resolve (mono_domain_get ()))
+               return NULL;
+       
+       // Reconstruct the type name
+       fullName = g_string_new ("");
+       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);
+       for (mod = info->nested; mod; mod = mod->next)
+               g_string_append_printf (fullName, "+%s", (char*)mod->data);
+
+       assembly = 
+               mono_domain_try_type_resolve (
+                       mono_domain_get (), fullName->str, NULL);
+       if (assembly && (!image || (assembly->assembly->image == image)))
+               type = mono_reflection_get_type_internal (assembly->assembly->image, 
+                                                                                info, ignorecase);
+       g_string_free (fullName, TRUE);
+       return type;
+}
+
 /*
  * mono_reflection_type_from_name:
  * @name: type name.
@@ -3740,6 +4085,10 @@ handle_enum:
        case MONO_TYPE_CLASS: {
                char *n;
                MonoType *t;
+               if (*p == (char)0xFF) {
+                       *end = p + 1;
+                       return NULL;
+               }
 handle_type:
                slen = mono_metadata_decode_value (p, &p);
                n = g_memdup (p, slen + 1);
@@ -3759,6 +4108,9 @@ handle_type:
 
                if (subt == 0x50) {
                        goto handle_type;
+               } else if (subt == 0x0E) {
+                       type = MONO_TYPE_STRING;
+                       goto handle_enum;
                } else if (subt == 0x55) {
                        char *n;
                        MonoType *t;
@@ -3787,10 +4139,14 @@ handle_type:
        case MONO_TYPE_SZARRAY:
        {
                MonoArray *arr;
-               guint32 i,alen;
-               alen=read32(p);
-               p+=4;
-               arr=mono_array_new(mono_domain_get(),mono_class_from_mono_type(t->data.type),alen);
+               guint32 i, alen;
+               alen = read32 (p);
+               p += 4;
+               if (alen == 0xffffffff) {
+                       *end = p;
+                       return NULL;
+               }
+               arr = mono_array_new (mono_domain_get(), mono_class_from_mono_type (t->data.type), alen);
                switch (t->data.type->type)
                {
                        case MONO_TYPE_U1:
@@ -3832,20 +4188,11 @@ handle_type:
                                        p+=8;
                                }
                                break;
+                       case MONO_TYPE_CLASS:
                        case MONO_TYPE_STRING:
-                               for (i=0;i<alen;i++)
-                               {
-                                       if (*p==(char)0xff)
-                                       {
-                                               mono_array_set(arr,gpointer,i,NULL);
-                                               p++;
-                                       }
-                                       else
-                                       {
-                                               slen=mono_metadata_decode_value(p,&p);
-                                               mono_array_set(arr,gpointer,i,mono_string_new_len(mono_domain_get(),p,slen));
-                                               p+=slen;
-                                       }
+                               for (i = 0; i < alen; i++) {
+                                       MonoObject *item = load_cattr_value (image, t->data.type, p, &p);
+                                       mono_array_set (arr, gpointer, i, item);
                                }
                                break;
                        default:
@@ -3860,27 +4207,6 @@ handle_type:
        return NULL;
 }
 
-/*
- * Optimization we could avoid mallocing() an little-endian archs that
- * don't crash with unaligned accesses.
- */
-static const char*
-fill_param_data (MonoImage *image, MonoMethodSignature *sig, guint32 blobidx, void **params) {
-       int len, i;
-       const char *p = mono_metadata_blob_heap (image, blobidx);
-
-       len = mono_metadata_decode_value (p, &p);
-       if (len < 2 || read16 (p) != 0x0001) /* Prolog */
-               return NULL;
-
-       /* skip prolog */
-       p += 2;
-       for (i = 0; i < sig->param_count; ++i) {
-               params [i] = load_cattr_value (image, sig->params [i], p, &p);
-       }
-       return p;
-}
-
 static gboolean
 type_is_reference (MonoType *type)
 {
@@ -3973,6 +4299,273 @@ find_event_index (MonoClass *klass, MonoEvent *event) {
        return 0;
 }
 
+static MonoObject*
+create_custom_attr (MonoImage *image, MonoMethod *method, 
+                                       const char *data, guint32 len)
+{
+       const char *p = data;
+       const char *named;
+       guint32 i, j, num_named;
+       MonoObject *attr;
+       void **params;
+
+       if (len < 2 || read16 (p) != 0x0001) /* Prolog */
+               return NULL;
+
+       mono_class_init (method->klass);
+       /*g_print ("got attr %s\n", method->klass->name);*/
+       
+       params = g_new (void*, method->signature->param_count);
+
+       /* skip prolog */
+       p += 2;
+       for (i = 0; i < method->signature->param_count; ++i) {
+               params [i] = load_cattr_value (image, method->signature->params [i], p, &p);
+       }
+
+       named = p;
+       attr = mono_object_new (mono_domain_get (), method->klass);
+       mono_runtime_invoke (method, attr, params, NULL);
+       free_param_data (method->signature, params);
+       g_free (params);
+       num_named = read16 (named);
+       named += 2;
+       for (j = 0; j < num_named; j++) {
+               gint name_len;
+               char *name, named_type, data_type;
+               named_type = *named++;
+               data_type = *named++; /* type of data */
+               if (data_type == 0x55) {
+                       gint type_len;
+                       char *type_name;
+                       if ((unsigned char) *named == 0x80) /* no idea what this is, but it looks optional */
+                               named++;
+                       type_len = mono_metadata_decode_blob_size (named, &named);
+                       type_name = g_malloc (type_len + 1);
+                       memcpy (type_name, named, type_len);
+                       type_name [type_len] = 0;
+                       named += type_len;
+                       /* FIXME: lookup the type and check type consistency */
+               }
+               name_len = mono_metadata_decode_blob_size (named, &named);
+               name = g_malloc (name_len + 1);
+               memcpy (name, named, name_len);
+               name [name_len] = 0;
+               named += name_len;
+               if (named_type == 0x53) {
+                       MonoClassField *field = mono_class_get_field_from_name (mono_object_class (attr), name);
+                       void *val = load_cattr_value (image, field->type, named, &named);
+                               mono_field_set_value (attr, field, val);
+                               if (!type_is_reference (field->type))
+                                       g_free (val);
+               } else if (named_type == 0x54) {
+                       MonoProperty *prop;
+                       void *pparams [1];
+                       MonoType *prop_type;
+
+                       prop = mono_class_get_property_from_name (mono_object_class (attr), name);
+                       /* can we have more that 1 arg in a custom attr named property? */
+                       prop_type = prop->get? prop->get->signature->ret: prop->set->signature->params [prop->set->signature->param_count - 1];
+                       pparams [0] = load_cattr_value (image, prop_type, named, &named);
+                       mono_property_set_value (prop, attr, pparams, NULL);
+                       if (!type_is_reference (prop_type))
+                               g_free (pparams [0]);
+               }
+               g_free (name);
+       }
+
+       return attr;
+}
+
+MonoArray*
+mono_custom_attrs_construct (MonoCustomAttrInfo *cinfo)
+{
+       MonoArray *result;
+       MonoClass *klass;
+       MonoObject *attr;
+       int i;
+
+       klass = mono_class_from_name (mono_defaults.corlib, "System", "Attribute");
+       result = mono_array_new (mono_domain_get (), klass, cinfo->num_attrs);
+       for (i = 0; i < cinfo->num_attrs; ++i) {
+               attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
+               mono_array_set (result, gpointer, i, attr);
+       }
+       return result;
+}
+
+MonoCustomAttrInfo*
+mono_custom_attrs_from_index (MonoImage *image, guint32 idx)
+{
+       guint32 mtoken, i, len;
+       guint32 cols [MONO_CUSTOM_ATTR_SIZE];
+       MonoTableInfo *ca;
+       MonoCustomAttrInfo *ainfo;
+       GList *tmp, *list = NULL;
+       const char *data;
+       
+       ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
+       /* the table is not sorted */
+       for (i = 0; i < ca->rows; ++i) {
+               if (mono_metadata_decode_row_col (ca, i, MONO_CUSTOM_ATTR_PARENT) != idx)
+                       continue;
+               list = g_list_prepend (list, GUINT_TO_POINTER (i));
+       }
+       len = g_list_length (list);
+       if (!len)
+               return NULL;
+       ainfo = g_malloc0 (sizeof (MonoCustomAttrInfo) + sizeof (MonoCustomAttrEntry) * (len - MONO_ZERO_LEN_ARRAY));
+       ainfo->num_attrs = len;
+       ainfo->image = image;
+       for (i = 0, tmp = list; i < len; ++i, tmp = tmp->next) {
+               mono_metadata_decode_row (ca, GPOINTER_TO_UINT (tmp->data), cols, MONO_CUSTOM_ATTR_SIZE);
+               mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> CUSTOM_ATTR_TYPE_BITS;
+               switch (cols [MONO_CUSTOM_ATTR_TYPE] & CUSTOM_ATTR_TYPE_MASK) {
+               case CUSTOM_ATTR_TYPE_METHODDEF:
+                       mtoken |= MONO_TOKEN_METHOD_DEF;
+                       break;
+               case CUSTOM_ATTR_TYPE_MEMBERREF:
+                       mtoken |= MONO_TOKEN_MEMBER_REF;
+                       break;
+               default:
+                       g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
+                       break;
+               }
+               ainfo->attrs [i].ctor = mono_get_method (image, mtoken, NULL);
+               if (!ainfo->attrs [i].ctor)
+                       g_error ("Can't find custom attr constructor image: %s mtoken: 0x%08x", image->name, mtoken);
+               data = mono_metadata_blob_heap (image, cols [MONO_CUSTOM_ATTR_VALUE]);
+               ainfo->attrs [i].data_size = mono_metadata_decode_value (data, &data);
+               ainfo->attrs [i].data = data;
+       }
+       g_list_free (list);
+
+       return ainfo;
+}
+
+MonoCustomAttrInfo*
+mono_custom_attrs_from_method (MonoMethod *method)
+{
+       MonoCustomAttrInfo *cinfo;
+       guint32 idx;
+       
+       if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, method)))
+               return cinfo;
+       idx = find_method_index (method);
+       idx <<= CUSTOM_ATTR_BITS;
+       idx |= CUSTOM_ATTR_METHODDEF;
+       return mono_custom_attrs_from_index (method->klass->image, idx);
+}
+
+MonoCustomAttrInfo*
+mono_custom_attrs_from_class (MonoClass *klass)
+{
+       MonoCustomAttrInfo *cinfo;
+       guint32 idx;
+       
+       if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, klass)))
+               return cinfo;
+       idx = mono_metadata_token_index (klass->type_token);
+       idx <<= CUSTOM_ATTR_BITS;
+       idx |= CUSTOM_ATTR_TYPEDEF;
+       return mono_custom_attrs_from_index (klass->image, idx);
+}
+
+MonoCustomAttrInfo*
+mono_custom_attrs_from_assembly (MonoAssembly *assembly)
+{
+       MonoCustomAttrInfo *cinfo;
+       guint32 idx;
+       
+       if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, assembly)))
+               return cinfo;
+       idx = 1; /* there is only one assembly */
+       idx <<= CUSTOM_ATTR_BITS;
+       idx |= CUSTOM_ATTR_ASSEMBLY;
+       return mono_custom_attrs_from_index (assembly->image, idx);
+}
+
+MonoCustomAttrInfo*
+mono_custom_attrs_from_property (MonoClass *klass, MonoProperty *property)
+{
+       MonoCustomAttrInfo *cinfo;
+       guint32 idx;
+       
+       if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, property)))
+               return cinfo;
+       idx = find_property_index (klass, property);
+       idx <<= CUSTOM_ATTR_BITS;
+       idx |= CUSTOM_ATTR_PROPERTY;
+       return mono_custom_attrs_from_index (klass->image, idx);
+}
+
+MonoCustomAttrInfo*
+mono_custom_attrs_from_event (MonoClass *klass, MonoEvent *event)
+{
+       MonoCustomAttrInfo *cinfo;
+       guint32 idx;
+       
+       if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, event)))
+               return cinfo;
+       idx = find_event_index (klass, event);
+       idx <<= CUSTOM_ATTR_BITS;
+       idx |= CUSTOM_ATTR_EVENT;
+       return mono_custom_attrs_from_index (klass->image, idx);
+}
+
+MonoCustomAttrInfo*
+mono_custom_attrs_from_field (MonoClass *klass, MonoClassField *field)
+{
+       MonoCustomAttrInfo *cinfo;
+       guint32 idx;
+       
+       if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, field)))
+               return cinfo;
+       idx = find_field_index (klass, field);
+       idx <<= CUSTOM_ATTR_BITS;
+       idx |= CUSTOM_ATTR_FIELDDEF;
+       return mono_custom_attrs_from_index (klass->image, idx);
+}
+
+MonoCustomAttrInfo*
+mono_custom_attrs_from_param (MonoMethod *method, guint32 param)
+{
+       MonoTableInfo *ca;
+       guint32 i, idx, method_index;
+       guint32 param_list, param_last, param_pos, found;
+       MonoImage *image;
+       
+       /* FIXME: handle dynamic custom attrs for parameters */
+       /*if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, field)))
+               return cinfo;*/
+       image = method->klass->image;
+       method_index = find_method_index (method);
+       ca = &image->tables [MONO_TABLE_METHOD];
+
+       param_list = mono_metadata_decode_row_col (ca, method_index - 1, MONO_METHOD_PARAMLIST);
+       if (method_index == ca->rows) {
+               ca = &image->tables [MONO_TABLE_PARAM];
+               param_last = ca->rows + 1;
+       } else {
+               param_last = mono_metadata_decode_row_col (ca, method_index, MONO_METHOD_PARAMLIST);
+               ca = &image->tables [MONO_TABLE_PARAM];
+       }
+       found = FALSE;
+       for (i = param_list; i < param_last; ++i) {
+               param_pos = mono_metadata_decode_row_col (ca, i - 1, MONO_PARAM_SEQUENCE);
+               if (param_pos == param) {
+                       found = TRUE;
+                       break;
+               }
+       }
+       if (!found)
+               return NULL;
+       idx = i;
+       idx <<= CUSTOM_ATTR_BITS;
+       idx |= CUSTOM_ATTR_PARAMDEF;
+       return mono_custom_attrs_from_index (image, idx);
+}
+
 /*
  * mono_reflection_get_custom_attrs:
  * @obj: a reflection object handle
@@ -3983,171 +4576,50 @@ find_event_index (MonoClass *klass, MonoEvent *event) {
 MonoArray*
 mono_reflection_get_custom_attrs (MonoObject *obj)
 {
-       guint32 idx, mtoken, i, len;
-       guint32 cols [MONO_CUSTOM_ATTR_SIZE];
        MonoClass *klass;
-       MonoImage *image;
-       MonoTableInfo *ca;
-       MonoMethod *method;
-       MonoObject *attr;
        MonoArray *result;
-       GList *list = NULL;
-       void **params;
+       MonoCustomAttrInfo *cinfo;
        
        MONO_ARCH_SAVE_REGS;
-       
+
        klass = obj->vtable->klass;
        /* FIXME: need to handle: Module */
        if (klass == mono_defaults.monotype_class) {
                MonoReflectionType *rtype = (MonoReflectionType*)obj;
                klass = mono_class_from_mono_type (rtype->type);
-               idx = mono_metadata_token_index (klass->type_token);
-               idx <<= CUSTOM_ATTR_BITS;
-               idx |= CUSTOM_ATTR_TYPEDEF;
-               image = klass->image;
+               cinfo = mono_custom_attrs_from_class (klass);
        } else if (strcmp ("Assembly", klass->name) == 0) {
                MonoReflectionAssembly *rassembly = (MonoReflectionAssembly*)obj;
-               idx = 1; /* there is only one assembly */
-               idx <<= CUSTOM_ATTR_BITS;
-               idx |= CUSTOM_ATTR_ASSEMBLY;
-               image = rassembly->assembly->image;
+               cinfo = mono_custom_attrs_from_assembly (rassembly->assembly);
        } else if (strcmp ("MonoProperty", klass->name) == 0) {
                MonoReflectionProperty *rprop = (MonoReflectionProperty*)obj;
-               idx = find_property_index (rprop->klass, rprop->property);
-               idx <<= CUSTOM_ATTR_BITS;
-               idx |= CUSTOM_ATTR_PROPERTY;
-               image = rprop->klass->image;
+               cinfo = mono_custom_attrs_from_property (rprop->klass, rprop->property);
        } else if (strcmp ("MonoEvent", klass->name) == 0) {
                MonoReflectionEvent *revent = (MonoReflectionEvent*)obj;
-               idx = find_event_index (revent->klass, revent->event);
-               idx <<= CUSTOM_ATTR_BITS;
-               idx |= CUSTOM_ATTR_EVENT;
-               image = revent->klass->image;
+               cinfo = mono_custom_attrs_from_event (revent->klass, revent->event);
        } else if (strcmp ("MonoField", klass->name) == 0) {
                MonoReflectionField *rfield = (MonoReflectionField*)obj;
-               idx = find_field_index (rfield->klass, rfield->field);
-               idx <<= CUSTOM_ATTR_BITS;
-               idx |= CUSTOM_ATTR_FIELDDEF;
-               image = rfield->klass->image;
+               cinfo = mono_custom_attrs_from_field (rfield->klass, rfield->field);
        } else if ((strcmp ("MonoMethod", klass->name) == 0) || (strcmp ("MonoCMethod", klass->name) == 0)) {
                MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
-               idx = find_method_index (rmethod->method);
-               idx <<= CUSTOM_ATTR_BITS;
-               idx |= CUSTOM_ATTR_METHODDEF;
-               image = rmethod->method->klass->image;
+               cinfo = mono_custom_attrs_from_method (rmethod->method);
        } else if (strcmp ("ParameterInfo", klass->name) == 0) {
                MonoReflectionParameter *param = (MonoReflectionParameter*)obj;
                MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
-               guint32 method_index = find_method_index (rmethod->method);
-               guint32 param_list, param_last, param_pos, found;
-
-               image = rmethod->method->klass->image;
-               ca = &image->tables [MONO_TABLE_METHOD];
-
-               param_list = mono_metadata_decode_row_col (ca, method_index - 1, MONO_METHOD_PARAMLIST);
-               if (method_index == ca->rows) {
-                       ca = &image->tables [MONO_TABLE_PARAM];
-                       param_last = ca->rows + 1;
-               } else {
-                       param_last = mono_metadata_decode_row_col (ca, method_index, MONO_METHOD_PARAMLIST);
-                       ca = &image->tables [MONO_TABLE_PARAM];
-               }
-               found = 0;
-               for (i = param_list; i < param_last; ++i) {
-                       param_pos = mono_metadata_decode_row_col (ca, i - 1, MONO_PARAM_SEQUENCE);
-                       if (param_pos == param->PositionImpl) {
-                               found = 1;
-                               break;
-                       }
-               }
-               if (!found)
-                       return mono_array_new (mono_domain_get (), mono_defaults.object_class, 0);
-               idx = i;
-               idx <<= CUSTOM_ATTR_BITS;
-               idx |= CUSTOM_ATTR_PARAMDEF;
+               cinfo = mono_custom_attrs_from_param (rmethod->method, param->PositionImpl);
+       } else if (strcmp ("AssemblyBuilder", klass->name) == 0) {
+               MonoReflectionAssemblyBuilder *assemblyb = (MonoReflectionAssemblyBuilder*)obj;
+               cinfo = mono_custom_attrs_from_builders (assemblyb->assembly.assembly->image, assemblyb->cattrs);
        } else { /* handle other types here... */
                g_error ("get custom attrs not yet supported for %s", klass->name);
        }
 
-       /* at this point image and index are set correctly for searching the custom attr */
-       ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
-       /* the table is not sorted */
-       for (i = 0; i < ca->rows; ++i) {
-               const char *named;
-               gint j, num_named;
-               mono_metadata_decode_row (ca, i, cols, MONO_CUSTOM_ATTR_SIZE);
-               if (cols [MONO_CUSTOM_ATTR_PARENT] != idx)
-                       continue;
-               mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> CUSTOM_ATTR_TYPE_BITS;
-               switch (cols [MONO_CUSTOM_ATTR_TYPE] & CUSTOM_ATTR_TYPE_MASK) {
-               case CUSTOM_ATTR_TYPE_METHODDEF:
-                       mtoken |= MONO_TOKEN_METHOD_DEF;
-                       break;
-               case CUSTOM_ATTR_TYPE_MEMBERREF:
-                       mtoken |= MONO_TOKEN_MEMBER_REF;
-                       break;
-               default:
-                       g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
-                       break;
-               }
-               method = mono_get_method (image, mtoken, NULL);
-               if (!method)
-                       g_error ("Can't find custom attr constructor image: %s mtoken: 0x%08x", image->name, mtoken);
-               mono_class_init (method->klass);
-               /*g_print ("got attr %s\n", method->klass->name);*/
-               params = g_new (void*, method->signature->param_count);
-               named = fill_param_data (image, method->signature, cols [MONO_CUSTOM_ATTR_VALUE], params);
-               attr = mono_object_new (mono_domain_get (), method->klass);
-               mono_runtime_invoke (method, attr, params, NULL);
-               free_param_data (method->signature, params);
-               g_free (params);
-               num_named = read16 (named);
-               named += 2;
-               for (j = 0; j < num_named; j++) {
-                       gint name_len;
-                       char *name, named_type;
-                       named_type = *named++;
-                       named++; /* type of data */
-                       name_len = mono_metadata_decode_blob_size (named, &named);
-                       name = g_malloc (name_len + 1);
-                       memcpy (name, named, name_len);
-                       name [name_len] = 0;
-                       named += name_len;
-                       if (named_type == 0x53) {
-                               MonoClassField *field = mono_class_get_field_from_name (mono_object_class (attr), name);
-                               void *val = load_cattr_value (image, field->type, named, &named);
-                               mono_field_set_value (attr, field, val);
-                               if (!type_is_reference (field->type))
-                                       g_free (val);
-                       } else if (named_type == 0x54) {
-                               MonoProperty *prop = mono_class_get_property_from_name (mono_object_class (attr), name);
-                               void *pparams [1];
-                               MonoType *prop_type;
-                               /* can we have more that 1 arg in a custom attr named property? */
-                               prop_type = prop->get? prop->get->signature->ret: prop->set->signature->params [prop->set->signature->param_count - 1];
-                               pparams [0] = load_cattr_value (image, prop_type, named, &named);
-                               mono_property_set_value (prop, attr, pparams, NULL);
-                               if (!type_is_reference (prop_type))
-                                       g_free (pparams [0]);
-                       }
-                       g_free (name);
-               }
-               list = g_list_prepend (list, attr);
-       }
-
-       len = g_list_length (list);
-       /*
-        * The return type is really object[], but System/Attribute.cs does a cast
-        * to (Attribute []) and that is not allowed: I'm lazy for now, but we should
-        * probably fix that.
-        */
-       klass = mono_class_from_name (mono_defaults.corlib, "System", "Attribute");
-       result = mono_array_new (mono_domain_get (), klass, len);
-       for (i = 0; i < len; ++i) {
-               mono_array_set (result, gpointer, i, list->data);
-               list = list->next;
+       if (cinfo) {
+               result = mono_custom_attrs_construct (cinfo);
+       } else {
+               klass = mono_class_from_name (mono_defaults.corlib, "System", "Attribute");
+               result = mono_array_new (mono_domain_get (), klass, 0);
        }
-       g_list_free (g_list_first (list));
 
        return result;
 }
@@ -4317,7 +4789,12 @@ handle_enum:
        case MONO_TYPE_CLASS: {
                char *str;
                guint32 slen;
-               MonoClass *k = mono_object_class (arg);
+               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")))
                        g_error ("only types allowed, not %s.%s", k->name_space, k->name);
@@ -4338,6 +4815,27 @@ handle_type:
                g_free (str);
                break;
        }
+       case MONO_TYPE_SZARRAY: {
+               int len, i;
+               MonoClass *eclass;
+
+               if (!arg) {
+                       *p++ = 0xff; *p++ = 0xff; *p++ = 0xff; *p++ = 0xff;
+                       break;
+               }
+               len = mono_array_length ((MonoArray*)arg);
+               *p++ = len & 0xff;
+               *p++ = (len >> 8) & 0xff;
+               *p++ = (len >> 16) & 0xff;
+               *p++ = (len >> 24) & 0xff;
+               *retp = p;
+               *retbuffer = buffer;
+               eclass = mono_class_from_mono_type (type)->element_class;
+               for (i = 0; i < len; ++i) {
+                       encode_cattr_value (buffer, p, &buffer, &p, buflen, &eclass->byval_arg, mono_array_get ((MonoArray*)arg, MonoObject*, i));
+               }
+               break;
+       }
        /* it may be a boxed value or a Type */
        case MONO_TYPE_OBJECT: {
                MonoClass *klass = mono_object_class (arg);
@@ -4349,6 +4847,10 @@ handle_type:
                        goto handle_type;
                } else if (klass->enumtype) {
                        *p++ = 0x55;
+               } else if (klass == mono_defaults.string_class) {
+                       simple_type = MONO_TYPE_STRING;
+                       *p++ = 0x0E;
+                       goto handle_enum;
                } else if (klass->byval_arg.type >= MONO_TYPE_BOOLEAN && klass->byval_arg.type <= MONO_TYPE_R8) {
                        *p++ = simple_type = klass->byval_arg.type;
                        goto handle_enum;
@@ -4408,38 +4910,15 @@ mono_reflection_get_custom_attrs_blob (MonoObject *ctor, MonoArray *ctorArgs, Mo
        } else {
                sig = ((MonoReflectionMethod*)ctor)->method->signature;
        }
+       g_assert (mono_array_length (ctorArgs) == sig->param_count);
        buflen = 256;
        p = buffer = g_malloc (buflen);
        /* write the prolog */
        *p++ = 1;
        *p++ = 0;
        for (i = 0; i < sig->param_count; ++i) {
-               if (sig->params[i]->type==MONO_TYPE_SZARRAY)
-               {
-                       guint32 alen=mono_array_length(ctorArgs) - i;
-                       guint32 j;
-                       if ((p-buffer) + 10 >= buflen) {
-                               char *newbuf;
-                               buflen *= 2;
-                               newbuf = g_realloc (buffer, buflen);
-                               p = newbuf + (p-buffer);
-                               buffer = newbuf;
-                       }
-                       *p++=alen&0xff;
-                       *p++=(alen>>8)&0xff;
-                       *p++=(alen>>16)&0xff;
-                       *p++=(alen>>24)&0xff;
-                       for (j=0;j<alen;j++)
-                       {
-                               arg=(MonoObject*)mono_array_get(ctorArgs,gpointer,i+j);
-                               encode_cattr_value(buffer,p,&buffer,&p,&buflen,sig->params[i]->data.type,arg);
-                       }
-               }
-               else
-               {
-                       arg = (MonoObject*)mono_array_get (ctorArgs, gpointer, i);
-                       encode_cattr_value (buffer, p, &buffer, &p, &buflen, sig->params [i], arg);
-               }
+               arg = mono_array_get (ctorArgs, MonoObject*, i);
+               encode_cattr_value (buffer, p, &buffer, &p, &buflen, sig->params [i], arg);
        }
        i = 0;
        if (properties)
@@ -4458,7 +4937,29 @@ mono_reflection_get_custom_attrs_blob (MonoObject *ctor, MonoArray *ctorArgs, Mo
                        prop = mono_array_get (properties, gpointer, i);
                        get_prop_name_and_type (prop, &pname, &ptype);
                        *p++ = 0x54; /* PROPERTY signature */
-                       mono_metadata_encode_value (ptype->type, p, &p);
+                       if (ptype->type == MONO_TYPE_VALUETYPE && ptype->data.klass->enumtype) {
+                               char *str = type_get_qualified_name (ptype, NULL);
+                               int slen = strlen (str);
+                               if ((p-buffer) + 10 + slen >= buflen) {
+                                       char *newbuf;
+                                       buflen *= 2;
+                                       buflen += slen;
+                                       newbuf = g_realloc (buffer, buflen);
+                                       p = newbuf + (p-buffer);
+                                       buffer = newbuf;
+                               }
+                               *p++ = 0x55;
+                               /*
+                                * This seems to be optional...
+                                * *p++ = 0x80;
+                                */
+                               mono_metadata_encode_value (slen, p, &p);
+                               memcpy (p, str, slen);
+                               p += slen;
+                               g_free (str);
+                       } else {
+                               mono_metadata_encode_value (ptype->type, p, &p);
+                       }
                        len = strlen (pname);
                        mono_metadata_encode_value (len, p, &p);
                        memcpy (p, pname, len);
@@ -4478,7 +4979,29 @@ mono_reflection_get_custom_attrs_blob (MonoObject *ctor, MonoArray *ctorArgs, Mo
                        field = mono_array_get (fields, gpointer, i);
                        get_field_name_and_type (field, &fname, &ftype);
                        *p++ = 0x53; /* FIELD signature */
-                       mono_metadata_encode_value (ftype->type, p, &p);
+                       if (ftype->type == MONO_TYPE_VALUETYPE && ftype->data.klass->enumtype) {
+                               char *str = type_get_qualified_name (ftype, NULL);
+                               int slen = strlen (str);
+                               if ((p-buffer) + 10 + slen >= buflen) {
+                                       char *newbuf;
+                                       buflen *= 2;
+                                       buflen += slen;
+                                       newbuf = g_realloc (buffer, buflen);
+                                       p = newbuf + (p-buffer);
+                                       buffer = newbuf;
+                               }
+                               *p++ = 0x55;
+                               /*
+                                * This seems to be optional...
+                                * *p++ = 0x80;
+                                */
+                               mono_metadata_encode_value (slen, p, &p);
+                               memcpy (p, str, slen);
+                               p += slen;
+                               g_free (str);
+                       } else {
+                               mono_metadata_encode_value (ftype->type, p, &p);
+                       }
                        len = strlen (fname);
                        mono_metadata_encode_value (len, p, &p);
                        memcpy (p, fname, len);
@@ -4556,12 +5079,19 @@ mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
        }
        mono_class_setup_mono_type (klass);
 
+       mono_class_setup_supertypes (klass);
+
        /*
         * FIXME: handle interfaces.
         */
 
        tb->type.type = &klass->byval_arg;
 
+       if (tb->nesting_type) {
+               g_assert (tb->nesting_type->type);
+               klass->nested_in = mono_class_from_mono_type (tb->nesting_type->type);
+       }
+
        /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
 }
 
@@ -4598,7 +5128,8 @@ mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
                 * this is almost safe to do with enums and it's needed to be able
                 * to create objects of the enum type (for use in SetConstant).
                 */
-               mono_class_setup_vtable (klass);
+               /* FIXME: Does this mean enums can't have method overrides ? */
+               mono_class_setup_vtable (klass, NULL, 0);
        }
 }
 
@@ -4624,15 +5155,17 @@ reflection_methodbuilder_to_mono_method (MonoClass *klass,
        m->name = mono_string_to_utf8 (rmb->name);
        m->klass = klass;
        m->signature = sig;
+       m->token = MONO_TOKEN_METHOD_DEF | (*rmb->table_idx);
 
-       /* TODO: What about m->token ? */
        if (m->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
                if (klass == mono_defaults.string_class && !strcmp (m->name, ".ctor"))
                        m->string_ctor = 1;
 
                m->addr = mono_lookup_internal_call (m);
+               m->signature->pinvoke = 1;
        } else if (m->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
                /* TODO */
+               m->signature->pinvoke = 1;
                return m;
        } else if (!m->klass->dummy && 
                           !(m->flags & METHOD_ATTRIBUTE_ABSTRACT) &&
@@ -4710,7 +5243,7 @@ ctorbuilder_to_mono_method (MonoClass *klass, MonoReflectionCtorBuilder* mb)
        rmb.ilgen = mb->ilgen;
        rmb.parameters = mb->parameters;
        rmb.pinfo = mb->pinfo;
-       rmb.attrs = mb->attrs;
+       rmb.attrs = mb->attrs | METHOD_ATTRIBUTE_RT_SPECIAL_NAME;
        rmb.iattrs = mb->iattrs;
        rmb.call_conv = mb->call_conv;
        rmb.type = mb->type;
@@ -4720,6 +5253,13 @@ ctorbuilder_to_mono_method (MonoClass *klass, MonoReflectionCtorBuilder* mb)
        rmb.code = NULL;
 
        mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
+       mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
+
+       if (!((MonoDynamicAssembly*)klass->image->assembly->dynamic)->save) {
+               /* ilgen is no longer needed */
+               mb->ilgen = NULL;
+       }
+
        return mb->mhandle;
 }
 
@@ -4744,6 +5284,12 @@ methodbuilder_to_mono_method (MonoClass *klass, MonoReflectionMethodBuilder* mb)
        rmb.code = mb->code;
 
        mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
+       mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
+
+       if (!((MonoDynamicAssembly*)klass->image->assembly->dynamic)->save) {
+               /* ilgen is no longer needed */
+               mb->ilgen = NULL;
+       }
        return mb->mhandle;
 }
 
@@ -4751,7 +5297,8 @@ static void
 ensure_runtime_vtable (MonoClass *klass)
 {
        MonoReflectionTypeBuilder *tb = klass->reflection_info;
-       int i, num, j;
+       int i, num, j, onum;
+       MonoMethod **overrides;
 
        if (!tb || klass->wastypebuilder)
                return;
@@ -4779,7 +5326,44 @@ ensure_runtime_vtable (MonoClass *klass)
                        klass->interfaces [i] = mono_class_from_mono_type (iface->type);
                }
        }
-       mono_class_setup_vtable (klass);
+
+       if (klass->flags & TYPE_ATTRIBUTE_INTERFACE)
+               for (i = 0; i < klass->method.count; ++i)
+                       klass->methods [i]->slot = i;
+
+       /* Overrides */
+       onum = 0;
+       if (tb->methods) {
+               for (i = 0; i < mono_array_length (tb->methods); ++i) {
+                       MonoReflectionMethodBuilder *mb = 
+                               mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
+                       if (mb->override_method)
+                               onum ++;
+               }
+       }
+
+       overrides = (MonoMethod**)g_new0 (MonoMethod, onum * 2);
+
+       if (tb->methods) {
+               onum = 0;
+               for (i = 0; i < mono_array_length (tb->methods); ++i) {
+                       MonoReflectionMethodBuilder *mb = 
+                               mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
+                       if (mb->override_method) {
+                               /* FIXME: What if 'override_method' is a MethodBuilder ? */
+                               overrides [onum * 2] = 
+                                       mb->override_method->method;
+                               overrides [onum * 2 + 1] =
+                                       mb->mhandle;
+
+                               g_assert (mb->mhandle);
+
+                               onum ++;
+                       }
+               }
+       }
+
+       mono_class_setup_vtable (klass, overrides, onum);
 }
 
 static void
@@ -4788,9 +5372,13 @@ typebuilder_setup_fields (MonoClass *klass)
        MonoReflectionTypeBuilder *tb = klass->reflection_info;
        MonoReflectionFieldBuilder *fb;
        MonoClassField *field;
+       const char *p, *p2;
        int i;
+       guint32 len, idx;
 
        klass->field.count = tb->fields? mono_array_length (tb->fields): 0;
+       klass->field.first = 0;
+       klass->field.last = klass->field.count;
 
        if (!klass->field.count)
                return;
@@ -4814,6 +5402,20 @@ typebuilder_setup_fields (MonoClass *klass)
                        field->offset = fb->offset;
                field->parent = klass;
                fb->handle = field;
+               mono_save_custom_attrs (klass->image, field, fb->cattrs);
+
+               if (fb->def_value) {
+                       field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
+                       MonoDynamicAssembly *assembly = klass->image->assembly->dynamic;
+                       field->def_value = g_new0 (MonoConstant, 1);
+                       idx = encode_constant (assembly, fb->def_value, &field->def_value->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;
+                       field->def_value->value = g_malloc (len);
+                       memcpy (field->def_value->value, p, len);
+               }
        }
        mono_class_layout_fields (klass);
 }
@@ -4828,10 +5430,11 @@ mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
 
        klass = my_mono_class_from_mono_type (tb->type.type);
 
+       mono_save_custom_attrs (klass->image, klass, tb->cattrs);
+
        /*
         * Fields to set in klass:
         * the various flags: delegate/unicode/contextbound etc.
-        * nested_in
         * nested_classes
         * properties
         * events
@@ -4839,6 +5442,10 @@ mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
        klass->flags = tb->attrs;
        klass->element_class = klass;
 
+       if (!((MonoDynamicAssembly*)klass->image->assembly->dynamic)->run)
+               /* No need to fully construct the type */
+               return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
+
        /* enums are done right away */
        if (!klass->enumtype)
                ensure_runtime_vtable (klass);
@@ -4854,6 +5461,7 @@ mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
                klass->instance_size = sizeof (MonoObject);
                klass->min_align = 1;
        }
+
        /* FIXME: handle packing_size and instance_size */
        typebuilder_setup_fields (klass);
 
@@ -4957,7 +5565,7 @@ mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token)
                        /* Type is not yet created */
                        MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
 
-                       mono_domain_try_type_resolve (mono_domain_get (), (MonoObject*)tb);
+                       mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
 
                        /*
                         * Hopefully this has been filled in by calling CreateType() on the
@@ -4977,7 +5585,7 @@ mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token)
                if (!result) {
                        MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)cb->type;
 
-                       mono_domain_try_type_resolve (mono_domain_get (), (MonoObject*)tb);
+                       mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
                        result = cb->mhandle;
                }
        }
@@ -4992,7 +5600,7 @@ mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token)
                if (!result) {
                        MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)fb->typeb;
 
-                       mono_domain_try_type_resolve (mono_domain_get (), (MonoObject*)tb);
+                       mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
                        result = fb->handle;
                }
        }
@@ -5006,14 +5614,50 @@ mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token)
                        result = klass;
                }
                else {
-                       mono_domain_try_type_resolve (mono_domain_get (), (MonoObject*)tb);
+                       mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
                        result = tb->type.type->data.klass;
                        g_assert (result);
                }
        }
+       else if (strcmp (obj->vtable->klass->name, "SignatureHelper") == 0) {
+               MonoReflectionSigHelper *helper = (MonoReflectionSigHelper*)obj;
+               MonoMethodSignature *sig;
+               int nargs, i;
+
+               if (helper->arguments)
+                       nargs = mono_array_length (helper->arguments);
+               else
+                       nargs = 0;
+
+               sig = mono_metadata_signature_alloc (image, nargs);
+               sig->explicit_this = helper->call_conv & 64;
+               sig->hasthis = helper->call_conv & 32;
+
+               if (helper->call_conv == 0) /* unmanaged */
+                       sig->call_convention = helper->unmanaged_call_conv - 1;
+               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_array_get (helper->arguments, MonoReflectionType*, i);
+                       sig->params [i] = rt->type;
+               }
+
+               result = sig;
+       }
        else {
                g_print (obj->vtable->klass->name);
                g_assert_not_reached ();
        }
        return result;
 }
+
+
+
+