2004-09-02 Zoltan Varga <vargaz@freemail.hu>
[mono.git] / mono / metadata / reflection.c
index dd59e474914acd353efefb55ea6175e68237d4c2..dc70fab01662290b310d451fb0e144a6863fddf1 100644 (file)
@@ -63,6 +63,11 @@ typedef struct {
        gpointer *refs;
 } ReflectionMethodBuilder;
 
+typedef struct {
+       guint32 owner;
+       MonoReflectionGenericParam *gparam;
+} GenericParamTableEntry;
+
 const unsigned char table_sizes [64] = {
        MONO_MODULE_SIZE,
        MONO_TYPEREF_SIZE,
@@ -1080,7 +1085,7 @@ mono_image_add_cattrs (MonoDynamicImage *assembly, guint32 idx, guint32 type, Mo
        for (i = 0; i < count; ++i) {
                cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
                values [MONO_CUSTOM_ATTR_PARENT] = idx;
-               token = mono_image_create_token (assembly, (MonoObject*)cattr->ctor);
+               token = mono_image_create_token (assembly, (MonoObject*)cattr->ctor, FALSE);
                type = mono_metadata_token_index (token);
                type <<= MONO_CUSTOM_ATTR_TYPE_BITS;
                switch (mono_metadata_token_table (token)) {
@@ -1369,7 +1374,8 @@ mono_image_get_method_info (MonoReflectionMethodBuilder *mb, MonoDynamicImage *a
                values = table->values + table->rows * MONO_METHODIMPL_SIZE;
                values [MONO_METHODIMPL_CLASS] = tb->table_idx;
                values [MONO_METHODIMPL_BODY] = MONO_METHODDEFORREF_METHODDEF | (mb->table_idx << MONO_METHODDEFORREF_BITS);
-               tok = mono_image_create_token (assembly, (MonoObject*)mb->override_method);
+
+               tok = mono_image_create_token (assembly, (MonoObject*)mb->override_method, FALSE);
                switch (mono_metadata_token_table (tok)) {
                case MONO_TABLE_MEMBERREF:
                        tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODREF;
@@ -1995,6 +2001,25 @@ encode_constraints (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynam
 
 static void
 mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
+{
+       GenericParamTableEntry *entry;
+
+       /*
+        * The GenericParam table must be sorted according to the `owner' field.
+        * We need to do this sorting prior to writing the GenericParamConstraint
+        * table, since we have to use the final GenericParam table indices there
+        * and they must also be sorted.
+        */
+
+       entry = g_new0 (GenericParamTableEntry, 1);
+       entry->owner = owner;
+       entry->gparam = gparam;
+
+       g_ptr_array_add (assembly->gen_params, entry);
+}
+
+static void
+write_generic_param_entry (MonoDynamicImage *assembly, GenericParamTableEntry *entry)
 {
        MonoDynamicTable *table;
        MonoGenericParam *param;
@@ -2005,12 +2030,12 @@ mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 o
        table_idx = table->next_idx ++;
        values = table->values + table_idx * MONO_GENERICPARAM_SIZE;
 
-       param = gparam->type.type->data.generic_param;
+       param = entry->gparam->type.type->data.generic_param;
 
-       values [MONO_GENERICPARAM_OWNER] = owner;
-       if (gparam->has_value_type)
+       values [MONO_GENERICPARAM_OWNER] = entry->owner;
+       if (entry->gparam->has_value_type)
                values [MONO_GENERICPARAM_FLAGS] = 0x18;
-       else if (gparam->has_reference_type)
+       else if (entry->gparam->has_reference_type)
                values [MONO_GENERICPARAM_FLAGS] = 0x04;
        else
                values [MONO_GENERICPARAM_FLAGS] = 0x00;
@@ -2018,7 +2043,7 @@ mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 o
        values [MONO_GENERICPARAM_NAME] = string_heap_insert (&assembly->sheap, param->name);
        values [MONO_GENERICPARAM_KIND] = 0;
 
-       encode_constraints (gparam, table_idx, assembly);
+       encode_constraints (entry->gparam, table_idx, assembly);
 }
 
 static guint32
@@ -2262,7 +2287,7 @@ mono_image_get_varargs_method_token (MonoDynamicImage *assembly, guint32 origina
                                     const gchar *name, guint32 sig)
 {
        MonoDynamicTable *table;
-       guint32 parent, token;
+       guint32 token;
        guint32 *values;
        
        table = &assembly->tables [MONO_TABLE_MEMBERREF];
@@ -2443,6 +2468,19 @@ mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *m)
        return token;
 }
 
+static guint32
+mono_image_get_inflated_method_token (MonoDynamicImage *assembly, MonoMethod *m)
+{
+       MonoMethodInflated *imethod = (MonoMethodInflated *) m;
+       guint32 sig, token;
+
+       sig = method_encode_signature (assembly, imethod->declaring->signature);
+       token = mono_image_get_memberref_token (
+               assembly, &m->klass->byval_arg, m->name, sig);
+
+       return token;
+}
+
 static guint32
 create_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb)
 {
@@ -2742,19 +2780,6 @@ mono_image_get_type_info (MonoDomain *domain, MonoReflectionTypeBuilder *tb, Mon
                }
        }
 
-       /* handle generic parameters */
-       if (tb->generic_params) {
-               table = &assembly->tables [MONO_TABLE_GENERICPARAM];
-               table->rows += mono_array_length (tb->generic_params);
-               alloc_table (table, table->rows);
-               for (i = 0; i < mono_array_length (tb->generic_params); ++i) {
-                       guint32 owner = MONO_TYPEORMETHOD_TYPE | (tb->table_idx << MONO_TYPEORMETHOD_BITS);
-
-                       mono_image_get_generic_param_info (
-                               mono_array_get (tb->generic_params, MonoReflectionGenericParam*, i), owner, assembly);
-               }
-       }
-
        /* handle fields */
        if (tb->fields) {
                table = &assembly->tables [MONO_TABLE_FIELD];
@@ -2815,6 +2840,19 @@ mono_image_get_type_info (MonoDomain *domain, MonoReflectionTypeBuilder *tb, Mon
                                mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i), assembly);
        }
 
+       /* handle generic parameters */
+       if (tb->generic_params) {
+               table = &assembly->tables [MONO_TABLE_GENERICPARAM];
+               table->rows += mono_array_length (tb->generic_params);
+               alloc_table (table, table->rows);
+               for (i = 0; i < mono_array_length (tb->generic_params); ++i) {
+                       guint32 owner = MONO_TYPEORMETHOD_TYPE | (tb->table_idx << MONO_TYPEORMETHOD_BITS);
+
+                       mono_image_get_generic_param_info (
+                               mono_array_get (tb->generic_params, MonoReflectionGenericParam*, i), owner, assembly);
+               }
+       }
+
        mono_image_add_decl_security (assembly, 
                                                                  mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx),
                                                                  tb->permissions);
@@ -3136,6 +3174,15 @@ compare_nested (const void *a, const void *b)
        return a_values [MONO_NESTED_CLASS_NESTED] - b_values [MONO_NESTED_CLASS_NESTED];
 }
 
+static int
+compare_genericparam (const void *a, const void *b)
+{
+       const GenericParamTableEntry **a_entry = (const GenericParamTableEntry **) a;
+       const GenericParamTableEntry **b_entry = (const GenericParamTableEntry **) b;
+
+       return (*a_entry)->owner - (*b_entry)->owner;
+}
+
 static void
 pad_heap (MonoDynamicStream *sh)
 {
@@ -3146,6 +3193,11 @@ pad_heap (MonoDynamicStream *sh)
        }
 }
 
+static struct StreamDesc {
+       const char *name;
+       MonoDynamicStream *stream;
+} stream_desc [5];
+
 /*
  * build_compressed_metadata() fills in the blob of data that represents the 
  * raw metadata as it will be saved in the PE file. The five streams are output 
@@ -3169,10 +3221,11 @@ build_compressed_metadata (MonoDynamicImage *assembly)
        MonoImage *meta;
        unsigned char *p;
 
-       struct StreamDesc {
-               const char *name;
-               MonoDynamicStream *stream;
-       } stream_desc [5];
+       qsort (assembly->gen_params->pdata, assembly->gen_params->len, sizeof (gpointer), compare_genericparam);
+       for (i = 0; i < assembly->gen_params->len; i++){
+               GenericParamTableEntry *entry = g_ptr_array_index (assembly->gen_params, i);
+               write_generic_param_entry (assembly, entry);
+       }
 
        stream_desc[0].name  = "#~"; stream_desc[0].stream = &assembly->tstream;
        stream_desc[1].name  = "#Strings"; stream_desc[1].stream = &assembly->sheap;
@@ -3186,7 +3239,7 @@ build_compressed_metadata (MonoDynamicImage *assembly)
                | ((guint64)1 << MONO_TABLE_FIELDLAYOUT) | ((guint64)1 << MONO_TABLE_FIELDRVA)
                | ((guint64)1 << MONO_TABLE_IMPLMAP) | ((guint64)1 << MONO_TABLE_NESTEDCLASS)
                | ((guint64)1 << MONO_TABLE_METHODIMPL) | ((guint64)1 << MONO_TABLE_CUSTOMATTRIBUTE)
-               | ((guint64)1 << MONO_TABLE_DECLSECURITY);
+               | ((guint64)1 << MONO_TABLE_DECLSECURITY) | ((guint64)1 << MONO_TABLE_GENERICPARAM);
        
        /* Compute table sizes */
        /* the MonoImage has already been created in mono_image_basic_init() */
@@ -3319,6 +3372,7 @@ build_compressed_metadata (MonoDynamicImage *assembly)
        if (table->rows)
                qsort (table->values + MONO_NESTED_CLASS_SIZE, table->rows, sizeof (guint32) * MONO_NESTED_CLASS_SIZE, compare_nested);
 
+
        /* compress the tables */
        for (i = 0; i < 64; i++){
                int row, col;
@@ -3912,7 +3966,7 @@ mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj,
 
                sig = method_builder_encode_signature (assembly, &rmb);
 
-               parent = mono_image_create_token (assembly, obj);
+               parent = mono_image_create_token (assembly, obj, TRUE);
                g_assert (mono_metadata_token_table (parent) == MONO_TABLE_METHOD);
 
                parent = mono_metadata_token_index (parent) << MONO_MEMBERREF_PARENT_BITS;
@@ -3943,7 +3997,8 @@ mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj,
  *     TypeBuilder
  */
 guint32
-mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj)
+mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj,
+                        gboolean create_methodspec)
 {
        MonoClass *klass;
        guint32 token = 0;
@@ -3995,7 +4050,12 @@ mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj)
                        strcmp (klass->name, "MonoMethod") == 0) {
                MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
                if (m->method->signature->is_inflated) {
-                       token = mono_image_get_methodspec_token (assembly, m->method);
+                       if (create_methodspec)
+                               token = mono_image_get_methodspec_token (
+                                       assembly, m->method);
+                       else
+                               token = mono_image_get_inflated_method_token (
+                                       assembly, m->method);
                } else if (m->method->signature->generic_param_count) {
                        g_assert_not_reached ();
                } else if ((m->method->klass->image == &assembly->image) &&
@@ -4070,16 +4130,7 @@ create_dynamic_mono_image (MonoDynamicAssembly *assembly,
        MonoDynamicImage *image;
        int i;
 
-       /*
-        * We need to use the current ms version or the ms runtime it won't find
-        * the support dlls. D'oh!
-        * const char *version = "mono-" VERSION;
-        */
-       /*
-        * To make binaries default to the .Net 1.0 version
-        * const char *version = "v1.0.3705";
-        */
-       const char *version = "v1.1.4322";
+       const char *version = mono_get_runtime_version ();
 
 #if HAVE_BOEHM_GC
        image = GC_MALLOC (sizeof (MonoDynamicImage));
@@ -4108,6 +4159,7 @@ create_dynamic_mono_image (MonoDynamicAssembly *assembly,
        image->typespec = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
        image->typeref = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
        image->blob_cache = mono_g_hash_table_new ((GHashFunc)mono_blob_entry_hash, (GCompareFunc)mono_blob_entry_equal);
+       image->gen_params = g_ptr_array_new ();
 
        string_heap_init (&image->sheap);
        mono_image_add_stream_data (&image->us, "", 1);
@@ -5872,6 +5924,7 @@ handle_type:
                                }
                                break;
                        case MONO_TYPE_CLASS:
+                       case MONO_TYPE_OBJECT:
                        case MONO_TYPE_STRING:
                                for (i = 0; i < alen; i++) {
                                        MonoObject *item = load_cattr_value (image, &t->data.klass->byval_arg, p, &p);
@@ -6815,6 +6868,7 @@ mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
                g_free (klass->supertypes);
                klass->supertypes = NULL;
                mono_class_setup_parent (klass, parent);
+               mono_class_setup_mono_type (klass);
                return;
        }
        
@@ -7066,19 +7120,19 @@ reflection_methodbuilder_to_mono_method (MonoClass *klass,
                                                                 num_clauses);
                }
 
-               if (rmb->generic_params) {
-                       int count = mono_array_length (rmb->generic_params);
-                       header->gen_params = g_new0 (MonoGenericParam, count);
-                       for (i = 0; i < count; i++) {
-                               MonoReflectionGenericParam *gp =
-                                       mono_array_get (rmb->generic_params,
-                                                       MonoReflectionGenericParam*, i);
+               pm->header = header;
+       }
+
+       if (rmb->generic_params) {
+               int count = mono_array_length (rmb->generic_params);
+               pm->gen_params = g_new0 (MonoGenericParam, count);
+               for (i = 0; i < count; i++) {
+                       MonoReflectionGenericParam *gp =
+                               mono_array_get (rmb->generic_params,
+                                               MonoReflectionGenericParam*, i);
 
-                               header->gen_params [i] = *gp->type.type->data.generic_param;
-                       }
+                       pm->gen_params [i] = *gp->type.type->data.generic_param;
                }
-
-               pm->header = header;
        }
 
        if (rmb->refs) {
@@ -7228,7 +7282,7 @@ do_mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_a
 {
        MonoClass *klass;
        MonoReflectionTypeBuilder *tb = NULL;
-       MonoGenericInst *ginst;
+       MonoGenericInst *ginst, *cached;
        MonoDomain *domain;
        MonoType *geninst;
        int icount, i;
@@ -7275,20 +7329,22 @@ do_mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_a
                ginst->generic_type = kginst->generic_type;
        }
 
-       geninst = g_hash_table_lookup (klass->image->generic_inst_cache, ginst);
-       if (geninst) {
+       geninst = g_new0 (MonoType, 1);
+       geninst->type = MONO_TYPE_GENERICINST;
+
+       cached = g_hash_table_lookup (klass->image->generic_inst_cache, ginst);
+       if (cached) {
                g_free (ginst);
                mono_loader_unlock ();
+               geninst->data.generic_inst = cached;
                return geninst;
        }
 
+       geninst->data.generic_inst = ginst;
+
        ginst->context = g_new0 (MonoGenericContext, 1);
        ginst->context->ginst = ginst;
 
-       geninst = g_new0 (MonoType, 1);
-       geninst->type = MONO_TYPE_GENERICINST;
-       geninst->data.generic_inst = ginst;
-
        if (!strcmp (((MonoObject *) type)->vtable->klass->name, "TypeBuilder")) {
                tb = (MonoReflectionTypeBuilder *) type;
 
@@ -7323,7 +7379,7 @@ do_mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_a
 
        mono_class_create_generic (ginst);
 
-       g_hash_table_insert (klass->image->generic_inst_cache, ginst, geninst);
+       g_hash_table_insert (klass->image->generic_inst_cache, ginst, ginst);
 
        mono_loader_unlock ();
 
@@ -7432,7 +7488,7 @@ inflate_mono_method (MonoReflectionGenericInst *type, MonoMethod *method, MonoOb
 
        for (i = 0; i < gmethod->mtype_argc; i++) {
                MonoMethodNormal *mn = (MonoMethodNormal *) method;
-               MonoGenericParam *gparam = &mn->header->gen_params [i];
+               MonoGenericParam *gparam = &mn->gen_params [i];
 
                g_assert (gparam->pklass);
                gmethod->mtype_argv [i] = &gparam->pklass->byval_arg;