Merge pull request #615 from nealef/master
[mono.git] / mono / metadata / metadata.c
index 7bbe7a52f23651848ba8f54ebffe973dd8230399..40411911bcc6fed9a28fa5dfa6d1fbcd3ea4c85d 100644 (file)
@@ -10,9 +10,6 @@
  */
 
 #include <config.h>
-#ifdef HAVE_ALLOCA_H
-#include <alloca.h>
-#endif
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -27,7 +24,6 @@
 #include "verify-internals.h"
 #include "class.h"
 #include "marshal.h"
-#include "gc-internal.h"
 #include "debug-helpers.h"
 #include <mono/utils/mono-error-internals.h>
  
@@ -45,9 +41,7 @@ static gboolean mono_metadata_class_equal (MonoClass *c1, MonoClass *c2, gboolea
 static gboolean mono_metadata_fnptr_equal (MonoMethodSignature *s1, MonoMethodSignature *s2, gboolean signature_only);
 static gboolean _mono_metadata_generic_class_equal (const MonoGenericClass *g1, const MonoGenericClass *g2,
                                                    gboolean signature_only);
-static GSList* free_generic_inst_dependents (MonoGenericInst *ginst);
 static void free_generic_inst (MonoGenericInst *ginst);
-static GSList* free_generic_class_dependents (MonoGenericClass *ginst);
 static void free_generic_class (MonoGenericClass *ginst);
 static void free_inflated_method (MonoMethodInflated *method);
 static void free_inflated_signature (MonoInflatedMethodSignature *sig);
@@ -763,7 +757,6 @@ mono_metadata_compute_size (MonoImage *meta, int tableindex, guint32 *result_bit
                        n = MAX (n, meta->tables [MONO_TABLE_METHOD].rows);
                        n = MAX (n, meta->tables [MONO_TABLE_MODULEREF].rows);
                        n = MAX (n, meta->tables [MONO_TABLE_TYPESPEC].rows);
-                       n = MAX (n, meta->tables [MONO_TABLE_MEMBERREF].rows);
 
                        /* 3 bits to encode */
                        field_size = rtsize (n, 16 - 3);
@@ -889,6 +882,7 @@ mono_metadata_locate_token (MonoImage *meta, guint32 token)
 const char *
 mono_metadata_string_heap (MonoImage *meta, guint32 index)
 {
+       g_assert (index < meta->heap_strings.size);
        g_return_val_if_fail (index < meta->heap_strings.size, "");
        return meta->heap_strings.data + index;
 }
@@ -903,6 +897,7 @@ mono_metadata_string_heap (MonoImage *meta, guint32 index)
 const char *
 mono_metadata_user_string (MonoImage *meta, guint32 index)
 {
+       g_assert (index < meta->heap_us.size);
        g_return_val_if_fail (index < meta->heap_us.size, "");
        return meta->heap_us.data + index;
 }
@@ -917,6 +912,7 @@ mono_metadata_user_string (MonoImage *meta, guint32 index)
 const char *
 mono_metadata_blob_heap (MonoImage *meta, guint32 index)
 {
+       g_assert (index < meta->heap_blob.size);
        g_return_val_if_fail (index < meta->heap_blob.size, "");/*FIXME shouldn't we return NULL and check for index == 0?*/
        return meta->heap_blob.data + index;
 }
@@ -2280,6 +2276,60 @@ delete_image_set (MonoImageSet *set)
        g_free (set);
 }
 
+static void
+mono_image_set_lock (MonoImageSet *set)
+{
+       EnterCriticalSection (&set->lock);
+}
+
+static void
+mono_image_set_unlock (MonoImageSet *set)
+{
+       LeaveCriticalSection (&set->lock);
+}
+
+gpointer
+mono_image_set_alloc (MonoImageSet *set, guint size)
+{
+       gpointer res;
+
+       mono_image_set_lock (set);
+       if (!set->mempool)
+               set->mempool = mono_mempool_new_size (1024);
+       res = mono_mempool_alloc (set->mempool, size);
+       mono_image_set_unlock (set);
+
+       return res;
+}
+
+gpointer
+mono_image_set_alloc0 (MonoImageSet *set, guint size)
+{
+       gpointer res;
+
+       mono_image_set_lock (set);
+       if (!set->mempool)
+               set->mempool = mono_mempool_new_size (1024);
+       res = mono_mempool_alloc0 (set->mempool, size);
+       mono_image_set_unlock (set);
+
+       return res;
+}
+
+char*
+mono_image_set_strdup (MonoImageSet *set, const char *s)
+{
+       char *res;
+
+       mono_image_set_lock (set);
+       if (!set->mempool)
+               set->mempool = mono_mempool_new_size (1024);
+       res = mono_mempool_strdup (set->mempool, s);
+       mono_image_set_unlock (set);
+
+       return res;
+}
+
 /* 
  * Structure used by the collect_..._images functions to store the image list.
  */
@@ -2563,7 +2613,10 @@ mono_metadata_clean_for_image (MonoImage *image)
 
        //check_image_sets (image);
 
-       /* The data structures could reference each other so we delete them in two phases */
+       /*
+        * The data structures could reference each other so we delete them in two phases.
+        * This is required because of the hashing functions in gclass/ginst_cache.
+        */
        ginst_data.image = gclass_data.image = image;
        ginst_data.list = gclass_data.list = NULL;
        mono_loader_lock ();
@@ -2581,9 +2634,9 @@ mono_metadata_clean_for_image (MonoImage *image)
 
        /* Delete the removed items */
        for (l = ginst_data.list; l; l = l->next)
-               free_list = g_slist_concat (free_generic_inst_dependents (l->data), free_list);
+               free_generic_inst (l->data);
        for (l = gclass_data.list; l; l = l->next)
-               free_list = g_slist_concat (free_generic_class_dependents (l->data), free_list);
+               free_generic_class (l->data);
        g_slist_free (ginst_data.list);
        g_slist_free (gclass_data.list);
        /* delete_image_set () modifies the lists so make a copy */
@@ -2627,86 +2680,23 @@ free_inflated_method (MonoMethodInflated *imethod)
 }
 
 static void
-free_list_with_data (GSList *l)
-{
-       while (l) {
-               g_free (l->data);
-               l = g_slist_delete_link (l, l);
-       }
-}
-
-static GSList*
-free_generic_inst_dependents (MonoGenericInst *ginst)
+free_generic_inst (MonoGenericInst *ginst)
 {
        int i;
 
+       /* The ginst itself is allocated from the image set mempool */
        for (i = 0; i < ginst->type_argc; ++i)
                mono_metadata_free_type (ginst->type_argv [i]);
-       return g_slist_prepend (NULL, ginst);
-}
-
-static void
-free_generic_inst (MonoGenericInst *ginst)
-{
-       free_list_with_data (free_generic_inst_dependents (ginst));
-}
-
-static GSList*
-free_generic_class_dependents (MonoGenericClass *gclass)
-{
-       GSList *l = NULL;
-       int i;
-
-       /* FIXME: The dynamic case */
-       if (gclass->cached_class && !gclass->cached_class->image->dynamic && !mono_generic_class_is_generic_type_definition (gclass)) {
-               MonoClass *class = gclass->cached_class;
-
-               /* Allocated in mono_class_init () */
-               g_free (class->methods);
-               if (class->ext) {
-                       g_free (class->ext->properties);
-                       g_free (class->ext->field_def_values);
-               }
-               /* Allocated in mono_class_setup_fields () */
-               g_free (class->fields);
-               /* Allocated in mono_class_setup_vtable_general () */
-               g_free (class->vtable);
-               /* Allocated in mono_generic_class_get_class () */
-               g_free (class->interfaces);
-               /* Allocated in setup_interface_offsets () */
-               g_free (class->interfaces_packed);
-               g_free (class->interface_offsets_packed);
-               g_free (class->interface_bitmap);
-               /* Allocated in mono_class_setup_supertypes () */
-               g_free (class->supertypes);
-               l = g_slist_prepend (l, class);
-       } else if (gclass->is_dynamic) {
-               MonoDynamicGenericClass *dgclass = (MonoDynamicGenericClass *)gclass;
-
-               for (i = 0; i < dgclass->count_fields; ++i) {
-                       MonoClassField *field = dgclass->fields + i;
-                       mono_metadata_free_type (field->type);
-                       g_free ((char*)field->name);
-#if HAVE_SGEN_GC
-                       MONO_GC_UNREGISTER_ROOT (dgclass->field_objects [i]);
-#endif
-               }
-
-               g_free (dgclass->methods);
-               g_free (dgclass->ctors);
-               g_free (dgclass->fields);
-               g_free (dgclass->field_objects);
-               g_free (dgclass->field_generic_types);
-               if (!mono_generic_class_is_generic_type_definition (gclass))
-                       l = g_slist_prepend (l, gclass->cached_class);
-       }
-       return g_slist_prepend (l, gclass);
 }
 
 static void
 free_generic_class (MonoGenericClass *gclass)
 {
-       free_list_with_data (free_generic_class_dependents (gclass));
+       /* The gclass itself is allocated from the image set mempool */
+       if (gclass->is_dynamic)
+               mono_reflection_free_dynamic_generic_class (gclass);
+       if (gclass->cached_class && gclass->cached_class->interface_id)
+               mono_unload_interface_id (gclass->cached_class);
 }
 
 static void
@@ -2806,10 +2796,8 @@ mono_metadata_get_generic_inst (int type_argc, MonoType **type_argv)
                        break;
        is_open = (i < type_argc);
 
-       ginst = alloca (size);
-#ifndef MONO_SMALL_CONFIG
-       ginst->id = 0;
-#endif
+       ginst = g_alloca (size);
+       memset (ginst, 0, sizeof (MonoGenericInst));
        ginst->is_open = is_open;
        ginst->type_argc = type_argc;
        memcpy (ginst->type_argv, type_argv, type_argc * sizeof (MonoType *));
@@ -2826,7 +2814,7 @@ mono_metadata_get_generic_inst (int type_argc, MonoType **type_argv)
 
        ginst = g_hash_table_lookup (set->ginst_cache, ginst);
        if (!ginst) {
-               ginst = g_malloc (size);
+               ginst = mono_image_set_alloc0 (set, size);
 #ifndef MONO_SMALL_CONFIG
                ginst->id = ++next_generic_inst_id;
 #endif
@@ -2896,17 +2884,18 @@ mono_metadata_lookup_generic_class (MonoClass *container_class, MonoGenericInst
        }
 
        if (is_dynamic) {
-               MonoDynamicGenericClass *dgclass = g_new0 (MonoDynamicGenericClass, 1);
+               MonoDynamicGenericClass *dgclass = mono_image_set_new0 (set, MonoDynamicGenericClass, 1);
                gclass = &dgclass->generic_class;
                gclass->is_dynamic = 1;
        } else {
-               gclass = g_new0 (MonoGenericClass, 1);
+               gclass = mono_image_set_new0 (set, MonoGenericClass, 1);
        }
 
        gclass->is_tb_open = is_tb_open;
        gclass->container_class = container_class;
        gclass->context.class_inst = inst;
        gclass->context.method_inst = NULL;
+       gclass->owner = set;
        if (inst == container_class->generic_container->context.class_inst && !is_tb_open)
                gclass->cached_class = container_class;
 
@@ -3105,6 +3094,23 @@ mono_metadata_get_shared_type (MonoType *type)
        return NULL;
 }
 
+static gboolean
+compare_type_literals (int class_type, int type_type)
+{
+       /* byval_arg.type can be zero if we're decoding a type that references a class been loading.
+        * See mcs/test/gtest-440. and #650936.
+        * FIXME This better be moved to the metadata verifier as it can catch more cases.
+        */
+       if (!class_type)
+               return TRUE;
+       /* NET 1.1 assemblies might encode string and object in a denormalized way.
+        * See #675464.
+        */
+       if (type_type == MONO_TYPE_CLASS && (class_type == MONO_TYPE_STRING || class_type == MONO_TYPE_OBJECT))
+               return TRUE;
+       return class_type == type_type;
+}
+
 /* 
  * do_mono_metadata_parse_type:
  * @type: MonoType to be filled in with the return value
@@ -3162,14 +3168,8 @@ do_mono_metadata_parse_type (MonoType *type, MonoImage *m, MonoGenericContainer
                type->data.klass = class;
                if (!class)
                        return FALSE;
-               /* byval_arg.type can be zero if we're decoding a type that references a class been loading.
-                * See mcs/test/gtest-440. and #650936.
-                * FIXME This better be moved to the metadata verifier as it can catch more cases.
-                */
-               if (class->byval_arg.type && class->byval_arg.type != type->type) {
-                       printf ("me [%x] it [%x] -- '%s'\n", type->type, type->data.klass->byval_arg.type, mono_type_full_name (type));
+               if (!compare_type_literals (class->byval_arg.type, type->type))
                        return FALSE;
-               }
                break;
        }
        case MONO_TYPE_SZARRAY: {
@@ -4068,7 +4068,7 @@ mono_metadata_interfaces_from_typedef (MonoImage *meta, guint32 index, guint *co
  * 
  * Returns: the 1-based index into the TypeDef table of the type
  * where the type described by @index is nested.
- * Retruns 0 if @index describes a non-nested type.
+ * Returns 0 if @index describes a non-nested type.
  */
 guint32
 mono_metadata_nested_in_typedef (MonoImage *meta, guint32 index)
@@ -4243,10 +4243,7 @@ mono_backtrace (int limit)
 }
 #endif
 
-#ifndef __GNUC__
-/*#define __alignof__(a) sizeof(a)*/
-#define __alignof__(type) G_STRUCT_OFFSET(struct { char c; type x; }, x)
-#endif
+#define abi__alignof__(type) G_STRUCT_OFFSET(struct { char c; type x; }, x)
 
 /*
  * mono_type_size:
@@ -4263,7 +4260,7 @@ mono_type_size (MonoType *t, int *align)
                return 0;
        }
        if (t->byref) {
-               *align = __alignof__(gpointer);
+               *align = abi__alignof__(gpointer);
                return sizeof (gpointer);
        }
 
@@ -4272,40 +4269,40 @@ mono_type_size (MonoType *t, int *align)
                *align = 1;
                return 0;
        case MONO_TYPE_BOOLEAN:
-               *align = __alignof__(gint8);
+               *align = abi__alignof__(gint8);
                return 1;
        case MONO_TYPE_I1:
        case MONO_TYPE_U1:
-               *align = __alignof__(gint8);
+               *align = abi__alignof__(gint8);
                return 1;
        case MONO_TYPE_CHAR:
        case MONO_TYPE_I2:
        case MONO_TYPE_U2:
-               *align = __alignof__(gint16);
+               *align = abi__alignof__(gint16);
                return 2;               
        case MONO_TYPE_I4:
        case MONO_TYPE_U4:
-               *align = __alignof__(gint32);
+               *align = abi__alignof__(gint32);
                return 4;
        case MONO_TYPE_R4:
-               *align = __alignof__(float);
+               *align = abi__alignof__(float);
                return 4;
        case MONO_TYPE_I8:
        case MONO_TYPE_U8:
-               *align = __alignof__(gint64);
+               *align = abi__alignof__(gint64);
                return 8;               
        case MONO_TYPE_R8:
-               *align = __alignof__(double);
+               *align = abi__alignof__(double);
                return 8;               
        case MONO_TYPE_I:
        case MONO_TYPE_U:
-               *align = __alignof__(gpointer);
+               *align = abi__alignof__(gpointer);
                return sizeof (gpointer);
        case MONO_TYPE_STRING:
-               *align = __alignof__(gpointer);
+               *align = abi__alignof__(gpointer);
                return sizeof (gpointer);
        case MONO_TYPE_OBJECT:
-               *align = __alignof__(gpointer);
+               *align = abi__alignof__(gpointer);
                return sizeof (gpointer);
        case MONO_TYPE_VALUETYPE: {
                if (t->data.klass->enumtype)
@@ -4318,7 +4315,7 @@ mono_type_size (MonoType *t, int *align)
        case MONO_TYPE_PTR:
        case MONO_TYPE_FNPTR:
        case MONO_TYPE_ARRAY:
-               *align = __alignof__(gpointer);
+               *align = abi__alignof__(gpointer);
                return sizeof (gpointer);
        case MONO_TYPE_TYPEDBYREF:
                return mono_class_value_size (mono_defaults.typed_reference_class, (guint32*)align);
@@ -4334,14 +4331,14 @@ mono_type_size (MonoType *t, int *align)
                        else
                                return mono_class_value_size (mono_class_from_mono_type (t), (guint32*)align);
                } else {
-                       *align = __alignof__(gpointer);
+                       *align = abi__alignof__(gpointer);
                        return sizeof (gpointer);
                }
        }
        case MONO_TYPE_VAR:
        case MONO_TYPE_MVAR:
                /* FIXME: Martin, this is wrong. */
-               *align = __alignof__(gpointer);
+               *align = abi__alignof__(gpointer);
                return sizeof (gpointer);
        default:
                g_error ("mono_type_size: type 0x%02x unknown", t->type);
@@ -4368,7 +4365,7 @@ mono_type_stack_size_internal (MonoType *t, int *align, gboolean allow_open)
        int tmp;
 #if SIZEOF_VOID_P == SIZEOF_REGISTER
        int stack_slot_size = sizeof (gpointer);
-       int stack_slot_align = __alignof__ (gpointer);
+       int stack_slot_align = abi__alignof__ (gpointer);
 #elif SIZEOF_VOID_P < SIZEOF_REGISTER
        int stack_slot_size = SIZEOF_REGISTER;
        int stack_slot_align = SIZEOF_REGISTER;
@@ -4413,14 +4410,14 @@ mono_type_stack_size_internal (MonoType *t, int *align, gboolean allow_open)
                *align = stack_slot_align;
                return stack_slot_size * 3;
        case MONO_TYPE_R4:
-               *align = __alignof__(float);
+               *align = abi__alignof__(float);
                return sizeof (float);          
        case MONO_TYPE_I8:
        case MONO_TYPE_U8:
-               *align = __alignof__(gint64);
+               *align = abi__alignof__(gint64);
                return sizeof (gint64);         
        case MONO_TYPE_R8:
-               *align = __alignof__(double);
+               *align = abi__alignof__(double);
                return sizeof (double);
        case MONO_TYPE_VALUETYPE: {
                guint32 size;
@@ -4599,6 +4596,8 @@ mono_metadata_generic_param_equal (MonoGenericParam *p1, MonoGenericParam *p2, g
                return TRUE;
        if (mono_generic_param_num (p1) != mono_generic_param_num (p2))
                return FALSE;
+       if (p1->serial != p2->serial)
+               return FALSE;
 
        /*
         * We have to compare the image as well because if we didn't,
@@ -4644,6 +4643,9 @@ mono_metadata_class_equal (MonoClass *c1, MonoClass *c2, gboolean signature_only
        if (signature_only &&
            (c1->byval_arg.type == MONO_TYPE_SZARRAY) && (c2->byval_arg.type == MONO_TYPE_SZARRAY))
                return mono_metadata_class_equal (c1->byval_arg.data.klass, c2->byval_arg.data.klass, signature_only);
+       if (signature_only &&
+           (c1->byval_arg.type == MONO_TYPE_ARRAY) && (c2->byval_arg.type == MONO_TYPE_ARRAY))
+               return do_mono_metadata_type_equal (&c1->byval_arg, &c2->byval_arg, signature_only);
        return FALSE;
 }
 
@@ -5227,7 +5229,6 @@ mono_type_create_from_typespec (MonoImage *image, guint32 type_spec)
        const char *ptr;
        guint32 len;
        MonoType *type, *type2;
-       MonoType stack_type;
 
        mono_loader_lock ();
 
@@ -5249,15 +5250,8 @@ mono_type_create_from_typespec (MonoImage *image, guint32 type_spec)
 
        len = mono_metadata_decode_value (ptr, &ptr);
 
-       type = &stack_type;
-       memset (type, 0, MONO_SIZEOF_TYPE);
-
-       if (*ptr == MONO_TYPE_BYREF) {
-               type->byref = 1;
-               ptr++;
-       }
-
-       if (!do_mono_metadata_parse_type (type, image, NULL, FALSE, ptr, &ptr)) {
+       type = mono_metadata_parse_type_internal (image, NULL, MONO_PARSE_TYPE, 0, TRUE, ptr, &ptr);
+       if (!type) {
                mono_loader_unlock ();
                return NULL;
        }
@@ -5269,9 +5263,9 @@ mono_type_create_from_typespec (MonoImage *image, guint32 type_spec)
                return type2;
        }
 
-       type2 = mono_image_alloc (image, MONO_SIZEOF_TYPE);
-       memcpy (type2, type, MONO_SIZEOF_TYPE);
+       type2 = mono_metadata_type_dup (image, type);
        g_hash_table_insert (image->typespec_cache, GUINT_TO_POINTER (type_spec), type2);
+       mono_metadata_free_type (type);
 
        mono_loader_unlock ();
 
@@ -5431,7 +5425,17 @@ handle_enum:
                }
                *conv = MONO_MARSHAL_CONV_BOOL_I4;
                return MONO_NATIVE_BOOLEAN;
-       case MONO_TYPE_CHAR: return MONO_NATIVE_U2;
+       case MONO_TYPE_CHAR:
+               if (mspec) {
+                       switch (mspec->native) {
+                       case MONO_NATIVE_U2:
+                       case MONO_NATIVE_U1:
+                               return mspec->native;
+                       default:
+                               g_error ("cant marshal char to native type %02x", mspec->native);
+                       }
+               }
+               return unicode ? MONO_NATIVE_U2 : MONO_NATIVE_U1;
        case MONO_TYPE_I1: return MONO_NATIVE_I1;
        case MONO_TYPE_U1: return MONO_NATIVE_U1;
        case MONO_TYPE_I2: return MONO_NATIVE_I2;
@@ -5737,7 +5741,7 @@ get_constraints (MonoImage *image, int owner, MonoClass ***constraints, MonoGene
        }
        if (!found)
                return TRUE;
-       res = g_new0 (MonoClass*, found + 1);
+       res = mono_image_alloc0 (image, sizeof (MonoClass*) * (found + 1));
        for (i = 0, tmp = cons; i < found; ++i, tmp = tmp->next) {
                res [i] = tmp->data;
        }
@@ -5797,6 +5801,9 @@ mono_metadata_has_generic_params (MonoImage *image, guint32 token)
        return mono_metadata_get_generic_param_row (image, token, &owner);
 }
 
+/*
+ * Memory is allocated from IMAGE's mempool.
+ */
 gboolean
 mono_metadata_load_generic_param_constraints_full (MonoImage *image, guint32 token,
                                              MonoGenericContainer *container)
@@ -5822,6 +5829,7 @@ mono_metadata_load_generic_param_constraints_full (MonoImage *image, guint32 tok
  * Load the generic parameter constraints for the newly created generic type or method
  * represented by @token and @container.  The @container is the new container which has
  * been returned by a call to mono_metadata_load_generic_params() with this @token.
+ * Memory is allocated from IMAGE's mempool.
  */
 void
 mono_metadata_load_generic_param_constraints (MonoImage *image, guint32 token,