Make nested type loading lazier.
[mono.git] / mono / metadata / metadata.c
index a8c43f18afa34ad22dfa25727e975e4dfb420b7d..aafcbb55e121991306c9cc99078ec3dfe264769c 100644 (file)
@@ -1612,7 +1612,7 @@ mono_metadata_parse_type_internal (MonoImage *m, MonoGenericContainer *container
        if (rptr)
                *rptr = ptr;
 
-       if (!type->num_mods) {
+       if (!type->num_mods && !transient) {
                /* 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;
@@ -3510,6 +3510,7 @@ mono_metadata_parse_mh_full (MonoImage *m, MonoGenericContainer *container, cons
                                                                                                                                MONO_PARSE_LOCAL, 0, TRUE, locals_ptr, &locals_ptr);
                        if (!mh->locals [i]) {
                                g_free (clauses);
+                               g_free (mh);
                                return NULL;
                        }
                }
@@ -4553,9 +4554,20 @@ mono_metadata_type_hash (MonoType *t1)
        switch (t1->type) {
        case MONO_TYPE_VALUETYPE:
        case MONO_TYPE_CLASS:
-       case MONO_TYPE_SZARRAY:
-               /* check if the distribution is good enough */
-               return ((hash << 5) - hash) ^ mono_metadata_str_hash (t1->data.klass->name);
+       case MONO_TYPE_SZARRAY: {
+               MonoClass *class = t1->data.klass;
+               /*
+                * Dynamic classes must not be hashed on their type since it can change
+                * during runtime. For example, if we hash a reference type that is
+                * later made into a valuetype.
+                *
+                * This is specially problematic with generic instances since they are
+                * inserted in a bunch of hash tables before been finished.
+                */
+               if (class->image->dynamic)
+                       return (t1->byref << 6) | mono_metadata_str_hash (class->name);
+               return ((hash << 5) - hash) ^ mono_metadata_str_hash (class->name);
+       }
        case MONO_TYPE_PTR:
                return ((hash << 5) - hash) ^ mono_metadata_type_hash (t1->data.type);
        case MONO_TYPE_ARRAY: