2009-02-05 Zoltan Varga <vargaz@gmail.com>
[mono.git] / mono / metadata / metadata.c
index 16dd45a1d5e92d3fd94324560583ba7aa2897e3d..f00e0ef15a84b0f272c4adb21f694b9e40598f92 100644 (file)
@@ -5,10 +5,14 @@
  *   Miguel de Icaza (miguel@ximian.com)
  *   Paolo Molaro (lupus@ximian.com)
  *
- * (C) 2001-2002 Ximian, Inc.
+ * Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
+ * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
  */
 
 #include <config.h>
+#ifdef HAVE_ALLOCA_H
+#include <alloca.h>
+#endif
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -1855,6 +1859,17 @@ mono_metadata_signature_dup (MonoMethodSignature *sig)
        return mono_metadata_signature_dup_full (NULL, sig);
 }
 
+/*
+ * mono_metadata_signature_size:
+ *
+ *   Return the amount of memory allocated to SIG.
+ */
+guint32
+mono_metadata_signature_size (MonoMethodSignature *sig)
+{
+       return sizeof (MonoMethodSignature) + (sig->param_count - MONO_ZERO_LEN_ARRAY) * sizeof (MonoType *);
+}
+
 /*
  * mono_metadata_parse_method_signature:
  * @m: metadata context
@@ -2121,6 +2136,20 @@ retry:
        case MONO_TYPE_VAR:
                if (type->data.generic_param->owner) {
                        g_assert (!type->data.generic_param->owner->is_method);
+                       /*
+                        * FIXME: The following check is here solely
+                        * for monodis, which uses the internal
+                        * function
+                        * mono_metadata_load_generic_params().  The
+                        * caller of that function needs to fill in
+                        * owner->klass or owner->method of the
+                        * returned struct, but monodis doesn't do
+                        * that.  The image unloading depends on that,
+                        * however, so a crash results without this
+                        * check.
+                        */
+                       if (!type->data.generic_param->owner->owner.klass)
+                               return FALSE;
                        return type->data.generic_param->owner->owner.klass->image == image;
                } else {
                        return type->data.generic_param->image == image;
@@ -2182,7 +2211,7 @@ inflated_method_in_image (gpointer key, gpointer value, gpointer data)
        // https://bugzilla.novell.com/show_bug.cgi?id=458168
        return method->declaring->klass->image == image ||
                (method->context.class_inst && ginst_in_image (method->context.class_inst, image)) ||
-               (method->context.method_inst && ginst_in_image (method->context.method_inst, image)) || signature_in_image (mono_method_signature ((MonoMethod*)method), image);
+               (method->context.method_inst && ginst_in_image (method->context.method_inst, image)) || (((MonoMethod*)method)->signature && signature_in_image (mono_method_signature ((MonoMethod*)method), image));
 }
 
 static gboolean
@@ -2257,7 +2286,6 @@ free_generic_inst (MonoGenericInst *ginst)
 
        for (i = 0; i < ginst->type_argc; ++i)
                mono_metadata_free_type (ginst->type_argv [i]);
-       g_free (ginst->type_argv);
        g_free (ginst);
 }
 
@@ -2376,40 +2404,37 @@ MonoGenericInst *
 mono_metadata_get_generic_inst (int type_argc, MonoType **type_argv)
 {
        MonoGenericInst *ginst;
-       MonoGenericInst helper;
+       gboolean is_open;
        int i;
-
-       helper.type_argc = type_argc;
-       helper.type_argv = type_argv;
-       helper.id = 0;
+       int size = sizeof (MonoGenericInst) + (type_argc - MONO_ZERO_LEN_ARRAY) * sizeof (MonoType *);
 
        for (i = 0; i < type_argc; ++i)
                if (mono_class_is_open_constructed_type (type_argv [i]))
                        break;
-       helper.is_open = (i < type_argc);
+       is_open = (i < type_argc);
+
+       ginst = alloca (size);
+       ginst->id = 0;
+       ginst->is_open = is_open;
+       ginst->type_argc = type_argc;
+       memcpy (ginst->type_argv, type_argv, type_argc * sizeof (MonoType *));
 
-       /*dump_ginst (&helper);*/
        mono_loader_lock ();
-       ginst = g_hash_table_lookup (generic_inst_cache, &helper);
-       if (ginst) {
-               mono_loader_unlock ();
-               /*g_print (" found cached\n");*/
-               return ginst;
-       }
 
-       ginst = g_new0 (MonoGenericInst, 1);
-       ginst->type_argc = type_argc;
-       ginst->type_argv = g_new (MonoType*, type_argc);
-       ginst->id = ++next_generic_inst_id;
-       ginst->is_open = helper.is_open;
+       ginst = g_hash_table_lookup (generic_inst_cache, ginst);
+       if (!ginst) {
+               ginst = g_malloc (size);
+               ginst->id = ++next_generic_inst_id;
+               ginst->is_open = is_open;
+               ginst->type_argc = type_argc;
 
-       for (i = 0; i < type_argc; ++i)
-               ginst->type_argv [i] = mono_metadata_type_dup (NULL, type_argv [i]);
+               for (i = 0; i < type_argc; ++i)
+                       ginst->type_argv [i] = mono_metadata_type_dup (NULL, type_argv [i]);
 
-       g_hash_table_insert (generic_inst_cache, ginst, ginst);
+               g_hash_table_insert (generic_inst_cache, ginst, ginst);
+       }
 
        mono_loader_unlock ();
-       /*g_print (" inserted\n");*/
        return ginst;
 }
 
@@ -3731,7 +3756,7 @@ mono_type_size (MonoType *t, int *align)
                return sizeof (gpointer);
        case MONO_TYPE_VALUETYPE: {
                if (t->data.klass->enumtype)
-                       return mono_type_size (t->data.klass->enum_basetype, align);
+                       return mono_type_size (mono_class_enum_basetype (t->data.klass), align);
                else
                        return mono_class_value_size (t->data.klass, (guint32*)align);
        }
@@ -3752,7 +3777,7 @@ mono_type_size (MonoType *t, int *align)
 
                if (container_class->valuetype) {
                        if (container_class->enumtype)
-                               return mono_type_size (container_class->enum_basetype, align);
+                               return mono_type_size (mono_class_enum_basetype (container_class), align);
                        else
                                return mono_class_value_size (mono_class_from_mono_type (t), (guint32*)align);
                } else {
@@ -3848,7 +3873,7 @@ mono_type_stack_size_internal (MonoType *t, int *align, gboolean allow_open)
                guint32 size;
 
                if (t->data.klass->enumtype)
-                       return mono_type_stack_size_internal (t->data.klass->enum_basetype, align, allow_open);
+                       return mono_type_stack_size_internal (mono_class_enum_basetype (t->data.klass), align, allow_open);
                else {
                        size = mono_class_value_size (t->data.klass, (guint32*)align);
 
@@ -3870,7 +3895,7 @@ mono_type_stack_size_internal (MonoType *t, int *align, gboolean allow_open)
 
                if (container_class->valuetype) {
                        if (container_class->enumtype)
-                               return mono_type_stack_size_internal (container_class->enum_basetype, align, allow_open);
+                               return mono_type_stack_size_internal (mono_class_enum_basetype (container_class), align, allow_open);
                        else {
                                guint32 size = mono_class_value_size (mono_class_from_mono_type (t), (guint32*)align);
 
@@ -3988,7 +4013,19 @@ mono_metadata_generic_param_equal (MonoGenericParam *p1, MonoGenericParam *p2, g
        if (p1->num != p2->num)
                return FALSE;
 
-       if (p1->owner == p2->owner)
+       /*
+        * We have to compare the image as well because if we didn't,
+        * the generic_inst_cache lookup wouldn't care about the image
+        * of generic params, so what could happen is that a generic
+        * inst with params from image A is put into the cache, then
+        * image B gets that generic inst from the cache, image A is
+        * unloaded, so the inst is deleted, but image B still retains
+        * a pointer to it.
+        *
+        * The AOT runtime doesn't set the image when it's decoding
+        * types, so we only compare it when the owner is NULL.
+        */
+       if (p1->owner == p2->owner && (p1->owner || p1->image == p2->image))
                return TRUE;
 
        /*
@@ -4279,12 +4316,12 @@ void
 mono_metadata_field_info (MonoImage *meta, guint32 index, guint32 *offset, guint32 *rva, 
                          MonoMarshalSpec **marshal_spec)
 {
-       return mono_metadata_field_info_with_mempool (NULL, meta, index, offset, rva, marshal_spec);
+       mono_metadata_field_info_with_mempool (NULL, meta, index, offset, rva, marshal_spec);
 }
 
 void
 mono_metadata_field_info_with_mempool (MonoMemPool *mempool, MonoImage *meta, guint32 index, guint32 *offset, guint32 *rva, 
-                         MonoMarshalSpec **marshal_spec)
+                                      MonoMarshalSpec **marshal_spec)
 {
        MonoTableInfo *tdef;
        locator_t loc;
@@ -4844,7 +4881,7 @@ handle_enum:
        case MONO_TYPE_PTR: return MONO_NATIVE_UINT;
        case MONO_TYPE_VALUETYPE: /*FIXME*/
                if (type->data.klass->enumtype) {
-                       t = type->data.klass->enum_basetype->type;
+                       t = mono_class_enum_basetype (type->data.klass)->type;
                        goto handle_enum;
                }
                if (type->data.klass == mono_defaults.handleref_class){
@@ -5200,12 +5237,11 @@ mono_metadata_load_generic_params (MonoImage *image, guint32 token, MonoGenericC
        do {
                n++;
                params = g_realloc (params, sizeof (MonoGenericParam) * n);
+               memset (&params [n - 1], 0, sizeof (MonoGenericParam));
                params [n - 1].owner = container;
-               params [n - 1].pklass = NULL;
                params [n - 1].flags = cols [MONO_GENERICPARAM_FLAGS];
                params [n - 1].num = cols [MONO_GENERICPARAM_NUMBER];
                params [n - 1].name = mono_metadata_string_heap (image, cols [MONO_GENERICPARAM_NAME]);
-               params [n - 1].constraints = NULL;
                if (++i > tdef->rows)
                        break;
                mono_metadata_decode_row (tdef, i - 1, cols, MONO_GENERICPARAM_SIZE);