Merge pull request #487 from mayerwin/patch-1
[mono.git] / mono / metadata / reflection.c
index 46ce7a02d4c01ebef08e37eb16d01a095d512f5f..0c3d2364822f6823828307a9b66db80e72c149dd 100644 (file)
@@ -6,6 +6,7 @@
  *
  * Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
  * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
+ * Copyright 2011 Rodrigo Kumpera
  *
  */
 #include <config.h>
@@ -1289,6 +1290,11 @@ mono_image_add_cattrs (MonoDynamicImage *assembly, guint32 idx, guint32 type, Mo
                switch (mono_metadata_token_table (token)) {
                case MONO_TABLE_METHOD:
                        type |= MONO_CUSTOM_ATTR_TYPE_METHODDEF;
+                       /*
+                        * fixup_cattrs () needs to fix this up. We can't use image->tokens, since it contains the old token for the
+                        * method, not the one returned by mono_image_create_token ().
+                        */
+                       mono_g_hash_table_insert (assembly->remapped_tokens, GUINT_TO_POINTER (token), cattr->ctor);
                        break;
                case MONO_TABLE_MEMBERREF:
                        type |= MONO_CUSTOM_ATTR_TYPE_MEMBERREF;
@@ -1542,29 +1548,35 @@ mono_image_add_methodimpl (MonoDynamicImage *assembly, MonoReflectionMethodBuild
        MonoDynamicTable *table;
        guint32 *values;
        guint32 tok;
+       MonoReflectionMethod *m;
+       int i;
 
-       if (!mb->override_method)
+       if (!mb->override_methods)
                return;
 
-       table = &assembly->tables [MONO_TABLE_METHODIMPL];
-       table->rows ++;
-       alloc_table (table, table->rows);
-       values = table->values + table->rows * MONO_METHODIMPL_SIZE;
-       values [MONO_METHODIMPL_CLASS] = tb->table_idx;
-       values [MONO_METHODIMPL_BODY] = MONO_METHODDEFORREF_METHODDEF | (mb->table_idx << MONO_METHODDEFORREF_BITS);
+       for (i = 0; i < mono_array_length (mb->override_methods); ++i) {
+               m = mono_array_get (mb->override_methods, MonoReflectionMethod*, i);
 
-       tok = mono_image_create_token (assembly, (MonoObject*)mb->override_method, FALSE, FALSE);
-       switch (mono_metadata_token_table (tok)) {
-       case MONO_TABLE_MEMBERREF:
-               tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODREF;
-               break;
-       case MONO_TABLE_METHOD:
-               tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODDEF;
-               break;
-       default:
-               g_assert_not_reached ();
+               table = &assembly->tables [MONO_TABLE_METHODIMPL];
+               table->rows ++;
+               alloc_table (table, table->rows);
+               values = table->values + table->rows * MONO_METHODIMPL_SIZE;
+               values [MONO_METHODIMPL_CLASS] = tb->table_idx;
+               values [MONO_METHODIMPL_BODY] = MONO_METHODDEFORREF_METHODDEF | (mb->table_idx << MONO_METHODDEFORREF_BITS);
+
+               tok = mono_image_create_token (assembly, (MonoObject*)m, FALSE, FALSE);
+               switch (mono_metadata_token_table (tok)) {
+               case MONO_TABLE_MEMBERREF:
+                       tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODREF;
+                       break;
+               case MONO_TABLE_METHOD:
+                       tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODDEF;
+                       break;
+               default:
+                       g_assert_not_reached ();
+               }
+               values [MONO_METHODIMPL_DECLARATION] = tok;
        }
-       values [MONO_METHODIMPL_DECLARATION] = tok;
 }
 
 #ifndef DISABLE_REFLECTION_EMIT
@@ -4322,13 +4334,17 @@ fixup_cattrs (MonoDynamicImage *assembly)
                if ((type & MONO_CUSTOM_ATTR_TYPE_MASK) == MONO_CUSTOM_ATTR_TYPE_METHODDEF) {
                        idx = type >> MONO_CUSTOM_ATTR_TYPE_BITS;
                        token = mono_metadata_make_token (MONO_TABLE_METHOD, idx);
-                       ctor = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
+                       ctor = mono_g_hash_table_lookup (assembly->remapped_tokens, GUINT_TO_POINTER (token));
                        g_assert (ctor);
 
                        if (!strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
                                MonoMethod *m = ((MonoReflectionMethod*)ctor)->method;
                                idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
                                values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
+                       } else if (!strcmp (ctor->vtable->klass->name, "ConstructorBuilder")) {
+                               MonoMethod *m = ((MonoReflectionCtorBuilder*)ctor)->mhandle;
+                               idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
+                               values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
                        }
                }
        }
@@ -4929,7 +4945,7 @@ mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj,
                if (tb->generic_params) {
                        token = mono_image_get_generic_field_token (assembly, fb);
                } else {
-                       if ((tb->module->dynamic_image == assembly)) {
+                       if (tb->module->dynamic_image == assembly) {
                                token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
                        } else {
                                token = mono_image_get_fieldref_token (assembly, (MonoObject*)fb, fb->handle);
@@ -5108,6 +5124,7 @@ create_dynamic_mono_image (MonoDynamicAssembly *assembly, char *assembly_name, c
        image->typeref = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
        image->blob_cache = g_hash_table_new ((GHashFunc)mono_blob_entry_hash, (GCompareFunc)mono_blob_entry_equal);
        image->gen_params = g_ptr_array_new ();
+       image->remapped_tokens = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC);
 
        /*g_print ("string heap create for image %p (%s)\n", image, module_name);*/
        string_heap_init (&image->sheap);
@@ -5148,6 +5165,26 @@ free_blob_cache_entry (gpointer key, gpointer val, gpointer user_data)
        g_free (key);
 }
 
+static void
+release_hashtable (MonoGHashTable **hash)
+{
+       if (*hash) {
+               mono_g_hash_table_destroy (*hash);
+               *hash = NULL;
+       }
+}
+
+void
+mono_dynamic_image_release_gc_roots (MonoDynamicImage *image)
+{
+       release_hashtable (&image->token_fixups);
+       release_hashtable (&image->handleref_managed);
+       release_hashtable (&image->tokens);
+       release_hashtable (&image->remapped_tokens);
+       release_hashtable (&image->generic_def_objects);
+       release_hashtable (&image->methodspec);
+}
+
 void
 mono_dynamic_image_free (MonoDynamicImage *image)
 {
@@ -5167,6 +5204,8 @@ mono_dynamic_image_free (MonoDynamicImage *image)
                mono_g_hash_table_destroy (di->handleref_managed);
        if (di->tokens)
                mono_g_hash_table_destroy (di->tokens);
+       if (di->remapped_tokens)
+               mono_g_hash_table_destroy (di->remapped_tokens);
        if (di->generic_def_objects)
                mono_g_hash_table_destroy (di->generic_def_objects);
        if (di->blob_cache) {
@@ -6823,7 +6862,7 @@ mono_param_get_objects_internal (MonoDomain *domain, MonoMethod *method, MonoCla
                }
 
                if (mspecs [i + 1])
-                       MONO_OBJECT_SETREF (param, MarshalAsImpl, (MonoObject*)mono_reflection_marshal_from_marshal_spec (domain, method->klass, mspecs [i + 1]));
+                       MONO_OBJECT_SETREF (param, MarshalAsImpl, (MonoObject*)mono_reflection_marshal_as_attribute_from_marshal_spec (domain, method->klass, mspecs [i + 1]));
                
                mono_array_setref (res, i, param);
        }
@@ -7897,7 +7936,7 @@ handle_type:
                val = load_cattr_value (image, &subc->byval_arg, p, end);
                obj = mono_object_new (mono_domain_get (), subc);
                g_assert (!subc->has_references);
-               memcpy ((char*)obj + sizeof (MonoObject), val, mono_class_value_size (subc, NULL));
+               mono_gc_memmove ((char*)obj + sizeof (MonoObject), val, mono_class_value_size (subc, NULL));
                g_free (val);
                return obj;
        }
@@ -9980,45 +10019,46 @@ mono_marshal_spec_from_builder (MonoImage *image, MonoAssembly *assembly,
 }
 #endif /* !DISABLE_REFLECTION_EMIT */
 
-MonoReflectionMarshal*
-mono_reflection_marshal_from_marshal_spec (MonoDomain *domain, MonoClass *klass,
+MonoReflectionMarshalAsAttribute*
+mono_reflection_marshal_as_attribute_from_marshal_spec (MonoDomain *domain, MonoClass *klass,
                                                                                   MonoMarshalSpec *spec)
 {
-       static MonoClass *System_Reflection_Emit_UnmanagedMarshalClass;
-       MonoReflectionMarshal *minfo;
+       static MonoClass *System_Reflection_Emit_MarshalAsAttribute;
+       MonoReflectionMarshalAsAttribute *minfo;
        MonoType *mtype;
 
-       if (!System_Reflection_Emit_UnmanagedMarshalClass) {
-               System_Reflection_Emit_UnmanagedMarshalClass = mono_class_from_name (
-                  mono_defaults.corlib, "System.Reflection.Emit", "UnmanagedMarshal");
-               g_assert (System_Reflection_Emit_UnmanagedMarshalClass);
+       if (!System_Reflection_Emit_MarshalAsAttribute) {
+               System_Reflection_Emit_MarshalAsAttribute = mono_class_from_name (
+                  mono_defaults.corlib, "System.Runtime.InteropServices", "MarshalAsAttribute");
+               g_assert (System_Reflection_Emit_MarshalAsAttribute);
        }
 
-       minfo = (MonoReflectionMarshal*)mono_object_new (domain, System_Reflection_Emit_UnmanagedMarshalClass);
-       minfo->type = spec->native;
+       minfo = (MonoReflectionMarshalAsAttribute*)mono_object_new (domain, System_Reflection_Emit_MarshalAsAttribute);
+       minfo->utype = spec->native;
 
-       switch (minfo->type) {
+       switch (minfo->utype) {
        case MONO_NATIVE_LPARRAY:
-               minfo->eltype = spec->data.array_data.elem_type;
-               minfo->count = spec->data.array_data.num_elem;
-               minfo->param_num = spec->data.array_data.param_num;
+               minfo->array_subtype = spec->data.array_data.elem_type;
+               minfo->size_const = spec->data.array_data.num_elem;
+               if (spec->data.array_data.param_num != -1)
+                       minfo->size_param_index = spec->data.array_data.param_num;
                break;
 
        case MONO_NATIVE_BYVALTSTR:
        case MONO_NATIVE_BYVALARRAY:
-               minfo->count = spec->data.array_data.num_elem;
+               minfo->size_const = spec->data.array_data.num_elem;
                break;
 
        case MONO_NATIVE_CUSTOM:
                if (spec->data.custom_data.custom_name) {
                        mtype = mono_reflection_type_from_name (spec->data.custom_data.custom_name, klass->image);
                        if (mtype)
-                               MONO_OBJECT_SETREF (minfo, marshaltyperef, mono_type_get_object (domain, mtype));
+                               MONO_OBJECT_SETREF (minfo, marshal_type_ref, mono_type_get_object (domain, mtype));
 
-                       MONO_OBJECT_SETREF (minfo, marshaltype, mono_string_new (domain, spec->data.custom_data.custom_name));
+                       MONO_OBJECT_SETREF (minfo, marshal_type, mono_string_new (domain, spec->data.custom_data.custom_name));
                }
                if (spec->data.custom_data.cookie)
-                       MONO_OBJECT_SETREF (minfo, mcookie, mono_string_new (domain, spec->data.custom_data.cookie));
+                       MONO_OBJECT_SETREF (minfo, marshal_cookie, mono_string_new (domain, spec->data.custom_data.cookie));
                break;
 
        default:
@@ -10590,9 +10630,7 @@ inflate_method (MonoReflectionType *type, MonoObject *obj)
 
 /*TODO avoid saving custom attrs for generic classes as it's enough to have them on the generic type definition.*/
 void
-mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *methods, 
-                                         MonoArray *ctors, MonoArray *fields, MonoArray *properties,
-                                         MonoArray *events)
+mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *fields)
 {
        MonoGenericClass *gclass;
        MonoDynamicGenericClass *dgclass;
@@ -10864,7 +10902,8 @@ void
 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides)
 {
        MonoReflectionTypeBuilder *tb;
-       int i, onum;
+       int i, j, onum;
+       MonoReflectionMethod *m;
 
        *overrides = NULL;
        *num_overrides = 0;
@@ -10883,8 +10922,8 @@ mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides
                for (i = 0; i < tb->num_methods; ++i) {
                        MonoReflectionMethodBuilder *mb = 
                                mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
-                       if (mb->override_method)
-                               onum ++;
+                       if (mb->override_methods)
+                               onum += mono_array_length (mb->override_methods);
                }
        }
 
@@ -10895,13 +10934,17 @@ mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides
                for (i = 0; i < tb->num_methods; ++i) {
                        MonoReflectionMethodBuilder *mb = 
                                mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
-                       if (mb->override_method) {
-                               (*overrides) [onum * 2] = mono_reflection_method_get_handle ((MonoObject *)mb->override_method);
-                               (*overrides) [onum * 2 + 1] = mb->mhandle;
+                       if (mb->override_methods) {
+                               for (j = 0; j < mono_array_length (mb->override_methods); ++j) {
+                                       m = mono_array_get (mb->override_methods, MonoReflectionMethod*, j);
 
-                               g_assert (mb->mhandle);
+                                       (*overrides) [onum * 2] = mono_reflection_method_get_handle ((MonoObject*)m);
+                                       (*overrides) [onum * 2 + 1] = mb->mhandle;
 
-                               onum ++;
+                                       g_assert (mb->mhandle);
+
+                                       onum ++;
+                               }
                        }
                }
        }
@@ -10926,7 +10969,11 @@ typebuilder_setup_fields (MonoClass *klass, MonoError *error)
        mono_error_init (error);
 
        if (tb->class_size) {
-               g_assert ((tb->packing_size & 0xfffffff0) == 0);
+               if ((tb->packing_size & 0xfffffff0) != 0) {
+                       char *err_msg = g_strdup_printf ("Could not load struct '%s' with packing size %d >= 16", klass->name, tb->packing_size);
+                       mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, err_msg);
+                       return;
+               }
                klass->packing_size = tb->packing_size;
                real_size = klass->instance_size + tb->class_size;
        }
@@ -10949,6 +10996,7 @@ typebuilder_setup_fields (MonoClass *klass, MonoError *error)
        klass->size_inited = 1;
 
        for (i = 0; i < klass->field.count; ++i) {
+               MonoArray *rva_data;
                fb = mono_array_get (tb->fields, gpointer, i);
                field = &klass->fields [i];
                field->name = mono_string_to_utf8_image (image, fb->name, error);
@@ -10960,8 +11008,14 @@ typebuilder_setup_fields (MonoClass *klass, MonoError *error)
                } else {
                        field->type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
                }
-               if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && fb->rva_data)
-                       klass->ext->field_def_values [i].data = mono_array_addr (fb->rva_data, char, 0);
+
+               if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && (rva_data = fb->rva_data)) {
+                       char *base = mono_array_addr (rva_data, char, 0);
+                       size_t size = mono_array_length (rva_data);
+                       char *data = mono_image_alloc (klass->image, size);
+                       memcpy (data, base, size);
+                       klass->ext->field_def_values [i].data = data;
+               }
                if (fb->offset != -1)
                        field->offset = fb->offset;
                field->parent = klass;
@@ -11919,7 +11973,14 @@ resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, Mon
                                is_sre_pointer (mono_object_get_class(obj))) {
                MonoReflectionType *ref_type = (MonoReflectionType *)obj;
                MonoType *type = mono_reflection_type_get_handle (ref_type);
-               result = mono_class_from_mono_type (type);
+
+               if (context) {
+                       MonoType *inflated = mono_class_inflate_generic_type (type, context);
+                       result = mono_class_from_mono_type (inflated);
+                       mono_metadata_free_type (inflated);
+               } else {
+                       result = mono_class_from_mono_type (type);
+               }
                *handle_class = mono_defaults.typehandle_class;
        } else {
                g_print ("%s\n", obj->vtable->klass->name);
@@ -12014,9 +12075,7 @@ mono_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject
 }
 
 void
-mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *methods, 
-                                         MonoArray *ctors, MonoArray *fields, MonoArray *properties,
-                                         MonoArray *events)
+mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *fields)
 {
        g_assert_not_reached ();
 }
@@ -12546,3 +12605,18 @@ mono_reflection_call_is_assignable_to (MonoClass *klass, MonoClass *oklass)
        else
                return *(MonoBoolean*)mono_object_unbox (res);
 }
+
+/**
+ * mono_reflection_type_get_type:
+ * @reftype: the System.Type object
+ *
+ * Returns the MonoType* associated with the C# System.Type object @reftype.
+ */
+MonoType*
+mono_reflection_type_get_type (MonoReflectionType *reftype)
+{
+       g_assert (reftype);
+
+       return mono_reflection_type_get_handle (reftype);
+}
+