2007-08-30 Dick Porter <dick@ximian.com>
[mono.git] / mono / metadata / metadata.c
index b171416b8b6e293564e19c06d28ad0827b1fe749..126f8708a4fabb8dc325a2216ca430ec87d02814 100644 (file)
@@ -1487,7 +1487,7 @@ mono_metadata_cleanup (void)
  * this MonoGenericContainer.
  * This is a Mono runtime internal function.
  *
- * LOCKING: Assumes the loader lock is held.
+ * LOCKING: Acquires the loader lock.
  *
  * Returns: a #MonoType structure representing the decoded type.
  */
@@ -1580,7 +1580,7 @@ mono_metadata_parse_type_full (MonoImage *m, MonoGenericContainer *container, Mo
        if (rptr)
                *rptr = ptr;
 
-               if (!type->num_mods) {
+       if (!type->num_mods) {
                /* no need to free type here, because it is on the stack */
                if ((type->type == MONO_TYPE_CLASS || type->type == MONO_TYPE_VALUETYPE) && !type->pinned && !type->attrs) {
                        MonoType *ret = type->byref ? &type->data.klass->this_arg : &type->data.klass->byval_arg;
@@ -2174,61 +2174,28 @@ static gboolean
 do_mono_metadata_parse_generic_class (MonoType *type, MonoImage *m, MonoGenericContainer *container,
                                      const char *ptr, const char **rptr)
 {
-       MonoGenericClass *gclass, *cached;
+       MonoGenericInst *inst;
        MonoClass *gklass;
        MonoType *gtype;
        int count;
 
-       gclass = g_new0 (MonoGenericClass, 1);
-
-       type->data.generic_class = gclass;
-
        gtype = mono_metadata_parse_type (m, MONO_PARSE_TYPE, 0, ptr, &ptr);
        if (gtype == NULL)
                return FALSE;
-       gclass->container_class = gklass = mono_class_from_mono_type (gtype);
 
-       g_assert (gklass->generic_container);
+       gklass = mono_class_from_mono_type (gtype);
+       if (!gklass->generic_container)
+               return FALSE;
 
        count = mono_metadata_decode_value (ptr, &ptr);
-
-       gclass->context.class_inst = mono_metadata_parse_generic_inst (m, container, count, ptr, &ptr);
-       gclass->context.method_inst = NULL;
+       inst = mono_metadata_parse_generic_inst (m, container, count, ptr, &ptr);
+       if (inst == NULL)
+               return FALSE;
 
        if (rptr)
                *rptr = ptr;
 
-       /* If we failed to parse, return, the error has been flagged. */
-       if (gclass->context.class_inst == NULL)
-               return FALSE;
-       
-       /*
-        * We may be called multiple times on different metadata to create the same
-        * instantiated type.  This happens for instance if we're part of a method or
-        * local variable signature.
-        *
-        * It's important to return the same MonoGenericClass * for each particualar
-        * instantiation of a generic type (ie "Stack<Int32>") to make static fields
-        * work.
-        *
-        * According to the spec ($26.1.5), a static variable in a generic class
-        * declaration is shared amongst all instances of the same closed constructed
-        * type.
-        */
-
-       cached = g_hash_table_lookup (generic_class_cache, gclass);
-       if (cached) {
-               g_free (gclass);
-
-               type->data.generic_class = cached;
-               return TRUE;
-       } else {
-               g_hash_table_insert (generic_class_cache, gclass, gclass);
-
-               mono_stats.generic_instance_count++;
-               mono_stats.generics_metadata_size += sizeof (MonoGenericClass) +
-                       gclass->context.class_inst->type_argc * sizeof (MonoType);
-       }
+       type->data.generic_class = mono_metadata_lookup_generic_class (gklass, inst, FALSE);
        return TRUE;
 }
 
@@ -3773,10 +3740,10 @@ mono_metadata_signature_equal (MonoMethodSignature *sig1, MonoMethodSignature *s
 
 /**
  * mono_metadata_type_dup:
- * @image: mempool to use
+ * @mp: mempool to use
  * @original: type to duplicate
  *
- * Returns: copy of type allocated from mempool.
+ * Returns: copy of type allocated from mempool (or from the heap, if @mp is null).
  */
 MonoType *
 mono_metadata_type_dup (MonoMemPool *mp, const MonoType *o)
@@ -4179,7 +4146,7 @@ mono_type_create_from_typespec (MonoImage *image, guint32 type_spec)
        guint32 cols [MONO_TYPESPEC_SIZE];
        const char *ptr;
        guint32 len;
-       MonoType *type;
+       MonoType *type, *type2;
 
        mono_loader_lock ();
 
@@ -4197,20 +4164,27 @@ mono_type_create_from_typespec (MonoImage *image, guint32 type_spec)
 
        type = g_new0 (MonoType, 1);
 
-       g_hash_table_insert (image->typespec_cache, GUINT_TO_POINTER (type_spec), type);
-
        if (*ptr == MONO_TYPE_BYREF) {
                type->byref = 1;
                ptr++;
        }
 
        if (!do_mono_metadata_parse_type (type, image, NULL, ptr, &ptr)) {
-               g_hash_table_remove (image->typespec_cache, GUINT_TO_POINTER (type_spec));
                g_free (type);
                mono_loader_unlock ();
                return NULL;
        }
 
+       type2 = g_hash_table_lookup (image->typespec_cache, GUINT_TO_POINTER (type_spec));
+
+       if (type2) {
+               g_free (type);
+               mono_loader_unlock ();
+               return type2;
+       }
+
+       g_hash_table_insert (image->typespec_cache, GUINT_TO_POINTER (type_spec), type);
+
        mono_loader_unlock ();
 
        return type;
@@ -4440,6 +4414,8 @@ handle_enum:
                        switch (mspec->native) {
                        case MONO_NATIVE_STRUCT:
                                return MONO_NATIVE_STRUCT;
+                       case MONO_NATIVE_CUSTOM:
+                               return MONO_NATIVE_CUSTOM;
                        case MONO_NATIVE_INTERFACE:
                                *conv = MONO_MARSHAL_CONV_OBJECT_INTERFACE;
                                return MONO_NATIVE_INTERFACE;