Revert patch as it introduced a regression while building: ** ERROR **: file metadat...
[mono.git] / mono / metadata / class.c
index 0f5f2ba6e3d4433ad6793dff11b5e0a2e2306084..f8fb5f366d850bcddc3306561991943c44645cc8 100644 (file)
@@ -74,11 +74,27 @@ mono_class_from_typeref (MonoImage *image, guint32 type_token)
        case MONO_RESOLTION_SCOPE_TYPEREF: {
                MonoClass *enclosing = mono_class_from_typeref (image, MONO_TOKEN_TYPE_REF | idx);
                GList *tmp;
-               mono_class_init (enclosing);
-               for (tmp = enclosing->nested_classes; tmp; tmp = tmp->next) {
-                       res = tmp->data;
-                       if (strcmp (res->name, name) == 0)
-                               return res;
+
+               if (enclosing->inited) {
+                       /* Micro-optimization: don't scan the metadata tables if enclosing is already inited */
+                       for (tmp = enclosing->nested_classes; tmp; tmp = tmp->next) {
+                               res = tmp->data;
+                               if (strcmp (res->name, name) == 0)
+                                       return res;
+                       }
+               } else {
+                       /* Don't call mono_class_init as we might've been called by it recursively */
+                       int i = mono_metadata_nesting_typedef (enclosing->image, enclosing->type_token, 1);
+                       while (i) {
+                               guint32 class_nested = mono_metadata_decode_row_col (&enclosing->image->tables [MONO_TABLE_NESTEDCLASS], i - 1, MONO_NESTED_CLASS_NESTED);
+                               guint32 string_offset = mono_metadata_decode_row_col (&enclosing->image->tables [MONO_TABLE_TYPEDEF], class_nested - 1, MONO_TYPEDEF_NAME);
+                               const char *nname = mono_metadata_string_heap (enclosing->image, string_offset);
+
+                               if (strcmp (nname, name) == 0)
+                                       return mono_class_create_from_typedef (enclosing->image, MONO_TOKEN_TYPE_DEF | class_nested);
+
+                               i = mono_metadata_nesting_typedef (enclosing->image, enclosing->type_token, i + 1);
+                       }
                }
                g_warning ("TypeRef ResolutionScope not yet handled (%d)", idx);
                return NULL;
@@ -107,10 +123,41 @@ dup_type (MonoType* t, const MonoType *original)
        r->byref = original->byref;
        if (t->type == MONO_TYPE_PTR)
                t->data.type = dup_type (t->data.type, original->data.type);
+       else if (t->type == MONO_TYPE_ARRAY)
+               t->data.array = mono_dup_array_type (t->data.array);
+       else if (t->type == MONO_TYPE_FNPTR)
+               t->data.method = mono_metadata_signature_deep_dup (t->data.method);
        mono_stats.generics_metadata_size += sizeof (MonoType);
        return r;
 }
 
+/* Copy everything mono_metadata_free_array free. */
+MonoArrayType *
+mono_dup_array_type (MonoArrayType *a)
+{
+       a = g_memdup (a, sizeof (MonoArrayType));
+       if (a->sizes)
+               a->sizes = g_memdup (a->sizes, a->numsizes * sizeof (int));
+       if (a->lobounds)
+               a->lobounds = g_memdup (a->lobounds, a->numlobounds * sizeof (int));
+       return a;
+}
+
+/* Copy everything mono_metadata_free_method_signature free. */
+MonoMethodSignature*
+mono_metadata_signature_deep_dup (MonoMethodSignature *sig)
+{
+       int i;
+       
+       sig = mono_metadata_signature_dup (sig);
+       
+       sig->ret = dup_type (sig->ret, sig->ret);
+       for (i = 0; i < sig->param_count; ++i)
+               sig->params [i] = dup_type (sig->params [i], sig->params [i]);
+       
+       return sig;
+}
+
 static void
 _mono_type_get_assembly_name (MonoClass *klass, GString *str)
 {
@@ -183,8 +230,7 @@ mono_type_get_name_recurse (MonoType *type, GString *str, gboolean is_recursed,
                                g_string_append_c (str, '.');
                        else
                                g_string_append_c (str, '+');
-               }
-               if (*klass->name_space) {
+               } else if (*klass->name_space) {
                        g_string_append (str, klass->name_space);
                        g_string_append_c (str, '.');
                }
@@ -589,14 +635,14 @@ mono_get_inflated_method (MonoMethod *method)
 }
 
 /** 
- * class_compute_field_layout:
+ * mono_class_setup_fields:
  * @m: pointer to the metadata.
  * @class: The class to initialize
  *
  * Initializes the class->fields.
  */
 static void
-class_compute_field_layout (MonoClass *class)
+mono_class_setup_fields (MonoClass *class)
 {
        MonoImage *m = class->image; 
        const int top = class->field.count;
@@ -611,9 +657,12 @@ class_compute_field_layout (MonoClass *class)
        if (class->size_inited)
                return;
 
+       class->instance_size = 0;
+       class->class_size = 0;
+
        if (class->parent) {
                if (!class->parent->size_inited)
-                       class_compute_field_layout (class->parent);
+                       mono_class_setup_fields (class->parent);
                class->instance_size += class->parent->instance_size;
                class->min_align = class->parent->min_align;
                /* we use |= since it may have been set already */
@@ -1786,17 +1835,7 @@ mono_class_init (MonoClass *class)
        }
 
        if (class->init_pending) {
-               /*
-                * We might be called recursively from mono_class_from_typeref if
-                * one of our fields has a type which is a nested type of this class,
-                * and the compiler encodes it as a typeref, like older versions of
-                * MS ilasm do.
-                */
-               if (class->size_inited) {
-                       mono_loader_unlock ();
-                       return;
-               }
-
+               mono_loader_unlock ();
                /* this indicates a cyclic dependency */
                g_error ("pending init %s.%s\n", class->name_space, class->name);
        }
@@ -1884,8 +1923,18 @@ mono_class_init (MonoClass *class)
        /*
         * Computes the size used by the fields, and their locations
         */
-       if (!class->size_inited)
-               class_compute_field_layout (class);
+       if (has_cached_info) {
+               class->instance_size = cached_info.instance_size;
+               class->class_size = cached_info.class_size;
+               class->packing_size = cached_info.packing_size;
+               class->min_align = cached_info.min_align;
+               class->blittable = cached_info.blittable;
+               class->has_references = cached_info.has_references;
+               class->has_static_refs = cached_info.has_static_refs;
+       }
+       else
+               if (!class->size_inited)
+                       mono_class_setup_fields (class);
 
        /* initialize method pointers */
        if (class->rank) {
@@ -2439,7 +2488,7 @@ mono_class_create_from_typedef (MonoImage *image, guint32 type_token)
        }
 
        if (class->enumtype)
-               class_compute_field_layout (class);
+               mono_class_setup_fields (class);
 
        if ((type_token = mono_metadata_nested_in_typedef (image, type_token)))
                class->nested_in = mono_class_create_from_typedef (image, type_token);
@@ -2781,7 +2830,7 @@ mono_class_create_from_typespec (MonoImage *image, guint32 type_spec,
 
        switch (type->type) {
        case MONO_TYPE_ARRAY:
-               class = mono_array_class_get (type->data.array->eklass, type->data.array->rank);
+               class = mono_bounded_array_class_get (type->data.array->eklass, type->data.array->rank, TRUE);
                break;
        case MONO_TYPE_SZARRAY:
                class = mono_array_class_get (type->data.klass, 1);
@@ -2896,7 +2945,7 @@ mono_bounded_array_class_get (MonoClass *eclass, guint32 rank, gboolean bounded)
        if (eclass->generic_class)
                mono_class_init (eclass);
        if (!eclass->size_inited)
-               class_compute_field_layout (eclass);
+               mono_class_setup_fields (eclass);
        class->has_references = MONO_TYPE_IS_REFERENCE (&eclass->byval_arg) || eclass->has_references? TRUE: FALSE;
 
        class->rank = rank;
@@ -3027,6 +3076,8 @@ mono_class_data_size (MonoClass *klass)
 static MonoClassField *
 mono_class_get_field_idx (MonoClass *class, int idx)
 {
+       mono_class_setup_fields (class);
+
        if (class->field.count){
                if ((idx >= class->field.first) && (idx < class->field.last)){
                        return &class->fields [idx - class->field.first];
@@ -3064,6 +3115,7 @@ mono_class_get_field_from_name (MonoClass *klass, const char *name)
        int i;
 
        while (klass) {
+               mono_class_setup_fields (klass);
                for (i = 0; i < klass->field.count; ++i) {
                        if (strcmp (name, klass->fields [i].name) == 0)
                                return &klass->fields [i];
@@ -3080,6 +3132,7 @@ mono_class_get_field_token (MonoClassField *field)
        int i;
 
        while (klass) {
+               mono_class_setup_fields (klass);
                for (i = 0; i < klass->field.count; ++i) {
                        if (&klass->fields [i] == field)
                                return mono_metadata_make_token (MONO_TABLE_FIELD, klass->field.first + i + 1);
@@ -3269,6 +3322,21 @@ mono_class_get_full (MonoImage *image, guint32 type_token, MonoGenericContext *c
        return mono_class_from_mono_type (inflated);
 }
 
+typedef struct {
+       gconstpointer key;
+       gpointer value;
+} FindUserData;
+
+static void
+find_nocase (gpointer key, gpointer value, gpointer user_data)
+{
+       char *name = (char*)key;
+       FindUserData *data = (FindUserData*)user_data;
+
+       if (!data->value && (g_strcasecmp (name, (char*)data->key) == 0))
+               data->value = value;
+}
+
 /**
  * mono_class_from_name_case:
  * @image: The MonoImage where the type is looked up in, or NULL for looking up in all loaded assemblies
@@ -3294,6 +3362,37 @@ mono_class_from_name_case (MonoImage *image, const char* name_space, const char
        const char *nspace;
        guint32 i, visib;
 
+       if (image->dynamic) {
+               guint32 token = 0;
+               FindUserData user_data;
+
+               mono_loader_lock ();
+
+               user_data.key = name_space;
+               user_data.value = NULL;
+               g_hash_table_foreach (image->name_cache, find_nocase, &user_data);
+
+               if (user_data.value) {
+                       GHashTable *nspace_table = (GHashTable*)user_data.value;
+
+                       user_data.key = name;
+                       user_data.value = NULL;
+
+                       g_hash_table_foreach (nspace_table, find_nocase, &user_data);
+                       
+                       if (user_data.value)
+                               token = GPOINTER_TO_UINT (user_data.value);
+               }
+
+               mono_loader_unlock ();
+               
+               if (token)
+                       return mono_class_get (image, MONO_TOKEN_TYPE_DEF | token);
+               else
+                       return NULL;
+
+       }
+
        /* add a cache if needed */
        for (i = 1; i <= t->rows; ++i) {
                mono_metadata_decode_row (t, i - 1, cols, MONO_TYPEDEF_SIZE);
@@ -3332,7 +3431,7 @@ return_nested_in (MonoClass *class, char *nested) {
 
 
 /**
- * mono_class_from_name_case:
+ * mono_class_from_name:
  * @image: The MonoImage where the type is looked up in, or NULL for looking up in all loaded assemblies
  * @name_space: the type namespace
  * @name: the type short name.
@@ -4027,6 +4126,7 @@ mono_class_get_fields (MonoClass* klass, gpointer *iter)
        if (!klass->inited)
                mono_class_init (klass);
        if (!*iter) {
+               mono_class_setup_fields (klass);
                /* start from the first */
                if (klass->field.count) {
                        return *iter = &klass->fields [0];
@@ -4529,7 +4629,7 @@ mono_class_get_exception_for_failure (MonoClass *klass)
                MonoDomain *domain = mono_domain_get ();
                MonoSecurityManager* secman = mono_security_manager_get_methods ();
                MonoMethod *method = klass->exception_data;
-               guint32 error = (method) ? MONO_METADATA_INHERITANCEDEMAND_CLASS : MONO_METADATA_INHERITANCEDEMAND_METHOD;
+               guint32 error = (method) ? MONO_METADATA_INHERITANCEDEMAND_METHOD : MONO_METADATA_INHERITANCEDEMAND_CLASS;
                MonoObject *exc = NULL;
                gpointer args [4];