X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mono%2Fmetadata%2Fclass.c;h=c96458b04a78f8bb95e70a53e8a1929e0a2fe831;hb=64e2556130a5220a09a770b85b442d0ff34bcbda;hp=dc1d8e1fa286b77edb10c91bfc5202c2e6648376;hpb=2958a0c88cabf1ee6436c3bb8d72615e32246793;p=mono.git diff --git a/mono/metadata/class.c b/mono/metadata/class.c index dc1d8e1fa28..c96458b04a7 100644 --- a/mono/metadata/class.c +++ b/mono/metadata/class.c @@ -4,10 +4,13 @@ * Author: * Miguel de Icaza (miguel@ximian.com) * - * (C) 2001-2006 Novell, Inc. - * + * Copyright 2001-2003 Ximian, Inc (http://www.ximian.com) + * Copyright 2004-2009 Novell, Inc (http://www.novell.com) */ #include +#ifdef HAVE_ALLOCA_H +#include +#endif #include #include #include @@ -35,10 +38,9 @@ #include #include #include +#include #include -#define MONO_CLASS_HAS_STATIC_METADATA(klass) ((klass)->type_token && !(klass)->image->dynamic && !(klass)->generic_class) - MonoStats mono_stats; gboolean mono_print_vtable = FALSE; @@ -607,6 +609,8 @@ mono_class_get_context (MonoClass *class) * The same as mono_class_inflate_generic_type, but allocates the MonoType * from mempool if it is non-NULL. If it is NULL, the MonoType is * allocated on the heap and is owned by the caller. + * The returned type can potentially be the same as TYPE, so it should not be + * modified by the caller, and it should be freed using mono_metadata_free_type (). */ MonoType* mono_class_inflate_generic_type_with_mempool (MonoMemPool *mempool, MonoType *type, MonoGenericContext *context) @@ -616,8 +620,15 @@ mono_class_inflate_generic_type_with_mempool (MonoMemPool *mempool, MonoType *ty if (context) inflated = inflate_generic_type (mempool, type, context); - if (!inflated) - return mono_metadata_type_dup (mempool, type); + if (!inflated) { + MonoType *shared = mono_metadata_get_shared_type (type); + + if (shared) { + return shared; + } else { + return mono_metadata_type_dup (mempool, type); + } + } mono_stats.inflated_type_count++; return inflated; @@ -640,6 +651,26 @@ mono_class_inflate_generic_type (MonoType *type, MonoGenericContext *context) return mono_class_inflate_generic_type_with_mempool (NULL, type, context); } +/* + * mono_class_inflate_generic_type_with_mempool_no_copy: + * + * Same as inflate_generic_type_with_mempool, but return TYPE if no inflation + * was done. + */ +static MonoType* +mono_class_inflate_generic_type_with_mempool_no_copy (MonoMemPool *mempool, MonoType *type, MonoGenericContext *context) +{ + MonoType *inflated = NULL; + + if (context) + inflated = inflate_generic_type (mempool, type, context); + + if (!inflated) + return type; + + mono_stats.inflated_type_count++; + return inflated; +} static MonoGenericContext inflate_generic_context (MonoGenericContext *context, MonoGenericContext *inflate_with) @@ -987,6 +1018,9 @@ mono_class_setup_fields (MonoClass *class) class->min_align = 1; } + if (class->simd_type) + class->min_align = 16; + /* Get the real size */ explicit_size = mono_metadata_packing_from_typedef (class->image, class->type_token, &packing_size, &real_size); @@ -1021,6 +1055,11 @@ mono_class_setup_fields (MonoClass *class) g_assert (container); mono_class_setup_fields (gklass); + + if (gklass->exception_type) { + mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL); + return; + } } /* @@ -1034,20 +1073,15 @@ mono_class_setup_fields (MonoClass *class) if (class->generic_class) { MonoClassField *gfield = &gklass->fields [i]; - MonoInflatedField *ifield = g_new0 (MonoInflatedField, 1); - ifield->generic_type = gfield->type; - field->name = gfield->name; - field->generic_info = ifield; + field->name = mono_field_get_name (gfield); /*This memory must come from the image mempool as we don't have a chance to free it.*/ - field->type = mono_class_inflate_generic_type_with_mempool (class->image->mempool, gfield->type, mono_class_get_context (class)); - field->type->attrs = gfield->type->attrs; + field->type = mono_class_inflate_generic_type_with_mempool_no_copy (class->image->mempool, gfield->type, mono_class_get_context (class)); + g_assert (field->type->attrs == gfield->type->attrs); if (mono_field_is_deleted (field)) continue; field->offset = gfield->offset; - field->data = gfield->data; } else { - guint32 rva; const char *sig; guint32 cols [MONO_FIELD_SIZE]; @@ -1072,14 +1106,7 @@ mono_class_setup_fields (MonoClass *class) field->offset = offset; if (field->offset == (guint32)-1 && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) g_warning ("%s not initialized correctly (missing field layout info for %s)", - class->name, field->name); - } - - if (field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) { - mono_metadata_field_info (m, idx, NULL, &rva, NULL); - if (!rva) - g_warning ("field %s in %s should have RVA data, but hasn't", field->name, class->name); - field->data = mono_image_rva_map (class->image, rva); + class->name, mono_field_get_name (field)); } } @@ -1323,7 +1350,7 @@ mono_class_layout_fields (MonoClass *class) } if ((top == 1) && (class->instance_size == sizeof (MonoObject)) && - (strcmp (field->name, "$PRIVATE$") == 0)) { + (strcmp (mono_field_get_name (field), "$PRIVATE$") == 0)) { /* This field is a hack inserted by MCS to empty structures */ continue; } @@ -1659,6 +1686,16 @@ mono_class_get_vtable_entry (MonoClass *class, int offset) return mono_class_inflate_generic_method_full (gklass->vtable [offset], class, mono_class_get_context (class)); } + if (class->rank == 1) { + /* + * szarrays do not overwrite any methods of Array, so we can avoid + * initializing their vtables in some cases. + */ + mono_class_setup_vtable (class->parent); + if (offset < class->parent->vtable_size) + return class->parent->vtable [offset]; + } + mono_class_setup_vtable (class); return class->vtable [offset]; } @@ -2061,9 +2098,57 @@ print_implemented_interfaces (MonoClass *klass) { } } +static MonoClass* +inflate_class_one_arg (MonoClass *gtype, MonoClass *arg0) +{ + MonoType *args [1]; + args [0] = &arg0->byval_arg; + + return mono_class_bind_generic_parameters (gtype, 1, args, FALSE); +} + +static MonoClass* +array_class_get_if_rank (MonoClass *class, guint rank) +{ + return rank ? mono_array_class_get (class, rank) : class; +} + +static void +fill_valuetype_array_derived_types (MonoClass **valuetype_types, MonoClass *eclass, int rank) +{ + valuetype_types [0] = eclass; + if (eclass == mono_defaults.int16_class) + valuetype_types [1] = mono_defaults.uint16_class; + else if (eclass == mono_defaults.uint16_class) + valuetype_types [1] = mono_defaults.int16_class; + else if (eclass == mono_defaults.int32_class) + valuetype_types [1] = mono_defaults.uint32_class; + else if (eclass == mono_defaults.uint32_class) + valuetype_types [1] = mono_defaults.int32_class; + else if (eclass == mono_defaults.int64_class) + valuetype_types [1] = mono_defaults.uint64_class; + else if (eclass == mono_defaults.uint64_class) + valuetype_types [1] = mono_defaults.int64_class; + else if (eclass == mono_defaults.byte_class) + valuetype_types [1] = mono_defaults.sbyte_class; + else if (eclass == mono_defaults.sbyte_class) + valuetype_types [1] = mono_defaults.byte_class; + else if (eclass->enumtype && eclass->enum_basetype) + valuetype_types [1] = mono_class_from_mono_type (eclass->enum_basetype); +} + /* this won't be needed once bug #325495 is completely fixed * though we'll need something similar to know which interfaces to allow * in arrays when they'll be lazyly created + * + * FIXME: System.Array/InternalEnumerator don't need all this interface fabrication machinery. + * MS returns diferrent types based on which instance is called. For example: + * object obj = new byte[10][]; + * Type a = ((IEnumerable)obj).GetEnumerator ().GetType (); + * Type b = ((IEnumerable>)obj).GetEnumerator ().GetType (); + * a != b ==> true + * + * Fixing this should kill quite some code, save some bits and improve compatbility. */ static MonoClass** get_implicit_generic_array_interfaces (MonoClass *class, int *num, int *is_enumerator) @@ -2072,9 +2157,9 @@ get_implicit_generic_array_interfaces (MonoClass *class, int *num, int *is_enume static MonoClass* generic_icollection_class = NULL; static MonoClass* generic_ienumerable_class = NULL; static MonoClass* generic_ienumerator_class = NULL; - MonoClass *fclass = NULL; + MonoClass *valuetype_types[2] = { NULL, NULL }; MonoClass **interfaces = NULL; - int i, interface_count, real_count; + int i, interface_count, real_count, original_rank; int all_interfaces; gboolean internal_enumerator; gboolean eclass_is_valuetype; @@ -2085,12 +2170,14 @@ get_implicit_generic_array_interfaces (MonoClass *class, int *num, int *is_enume } internal_enumerator = FALSE; eclass_is_valuetype = FALSE; + original_rank = eclass->rank; if (class->byval_arg.type != MONO_TYPE_SZARRAY) { if (class->generic_class && class->nested_in == mono_defaults.array_class && strcmp (class->name, "InternalEnumerator`1") == 0) { /* * For a Enumerator we need to get the list of interfaces for T. */ eclass = mono_class_from_mono_type (class->generic_class->context.class_inst->type_argv [0]); + original_rank = eclass->rank; eclass = eclass->element_class; internal_enumerator = TRUE; *is_enumerator = TRUE; @@ -2125,32 +2212,21 @@ get_implicit_generic_array_interfaces (MonoClass *class, int *num, int *is_enume * the generic interfaces needed to implement. */ if (eclass->valuetype) { - if (eclass == mono_defaults.int16_class) - fclass = mono_defaults.uint16_class; - else if (eclass == mono_defaults.uint16_class) - fclass = mono_defaults.int16_class; - else if (eclass == mono_defaults.int32_class) - fclass = mono_defaults.uint32_class; - else if (eclass == mono_defaults.uint32_class) - fclass = mono_defaults.int32_class; - else if (eclass == mono_defaults.int64_class) - fclass = mono_defaults.uint64_class; - else if (eclass == mono_defaults.uint64_class) - fclass = mono_defaults.int64_class; - else if (eclass == mono_defaults.byte_class) - fclass = mono_defaults.sbyte_class; - else if (eclass == mono_defaults.sbyte_class) - fclass = mono_defaults.byte_class; - else { - /* No additional interfaces for other value types */ - *num = 0; - return NULL; - } + fill_valuetype_array_derived_types (valuetype_types, eclass, original_rank); /* IList, ICollection, IEnumerable */ - real_count = interface_count = 3; - interfaces = g_malloc0 (sizeof (MonoClass*) * interface_count); - interfaces [0] = fclass; + real_count = interface_count = valuetype_types [1] ? 6 : 3; + if (internal_enumerator) { + ++real_count; + if (valuetype_types [1]) + ++real_count; + } + + interfaces = g_malloc0 (sizeof (MonoClass*) * real_count); + interfaces [0] = valuetype_types [0]; + if (valuetype_types [1]) + interfaces [3] = valuetype_types [1]; + eclass_is_valuetype = TRUE; } else { int j; @@ -2167,11 +2243,19 @@ get_implicit_generic_array_interfaces (MonoClass *class, int *num, int *is_enume interface_count++; else interface_count += idepth; + if (eclass->rank && eclass->element_class->valuetype) { + fill_valuetype_array_derived_types (valuetype_types, eclass->element_class, original_rank); + if (valuetype_types [1]) + ++interface_count; + } /* IList, ICollection, IEnumerable */ interface_count *= 3; real_count = interface_count; - if (internal_enumerator) - real_count += idepth + eclass->interface_offsets_count; + if (internal_enumerator) { + real_count += (MONO_CLASS_IS_INTERFACE (eclass) ? 1 : idepth) + eclass->interface_offsets_count; + if (valuetype_types [1]) + ++real_count; + } interfaces = g_malloc0 (sizeof (MonoClass*) * real_count); if (MONO_CLASS_IS_INTERFACE (eclass)) { interfaces [0] = mono_defaults.object_class; @@ -2195,59 +2279,58 @@ get_implicit_generic_array_interfaces (MonoClass *class, int *num, int *is_enume j += 3; } } + if (valuetype_types [1]) { + interfaces [j] = array_class_get_if_rank (valuetype_types [1], original_rank); + j += 3; + } } /* instantiate the generic interfaces */ for (i = 0; i < interface_count; i += 3) { - MonoType *args [1]; MonoClass *iface = interfaces [i]; - args [0] = &iface->byval_arg; - interfaces [i] = mono_class_bind_generic_parameters ( - mono_defaults.generic_ilist_class, 1, args, FALSE); - //g_print ("%s implements %s\n", class->name, mono_type_get_name_full (&interfaces [i]->byval_arg, 0)); - args [0] = &iface->byval_arg; - interfaces [i + 1] = mono_class_bind_generic_parameters ( - generic_icollection_class, 1, args, FALSE); - args [0] = &iface->byval_arg; - interfaces [i + 2] = mono_class_bind_generic_parameters ( - generic_ienumerable_class, 1, args, FALSE); - //g_print ("%s implements %s\n", class->name, mono_type_get_name_full (&interfaces [i + 1]->byval_arg, 0)); - //g_print ("%s implements %s\n", class->name, mono_type_get_name_full (&interfaces [i + 2]->byval_arg, 0)); + interfaces [i + 0] = inflate_class_one_arg (mono_defaults.generic_ilist_class, iface); + interfaces [i + 1] = inflate_class_one_arg (generic_icollection_class, iface); + interfaces [i + 2] = inflate_class_one_arg (generic_ienumerable_class, iface); } if (internal_enumerator) { int j; /* instantiate IEnumerator */ for (i = 0; i < interface_count; i++) { - MonoType *args [1]; - MonoClass *iface = interfaces [i]; - - args [0] = &iface->byval_arg; - interfaces [i] = mono_class_bind_generic_parameters ( - generic_ienumerator_class, 1, args, FALSE); - /*g_print ("%s implements %s\n", class->name, mono_type_get_name_full (&interfaces [i]->byval_arg, 0));*/ + interfaces [i] = inflate_class_one_arg (generic_ienumerator_class, interfaces [i]); } + j = interface_count; if (!eclass_is_valuetype) { - j = interface_count; - for (i = 0; i < eclass->idepth; i++) { - MonoType *args [1]; - args [0] = &eclass->supertypes [i]->byval_arg; - interfaces [j] = mono_class_bind_generic_parameters ( - generic_ienumerator_class, 1, args, FALSE); - /*g_print ("%s implements %s\n", class->name, mono_type_get_name_full (&interfaces [i]->byval_arg, 0));*/ + if (MONO_CLASS_IS_INTERFACE (eclass)) { + interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, mono_defaults.object_class); j ++; + } else { + for (i = 0; i < eclass->idepth; i++) { + interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, eclass->supertypes [i]); + j ++; + } } for (i = 0; i < eclass->interface_offsets_count; i++) { - MonoClass *iface = eclass->interfaces_packed [i]; - MonoType *args [1]; - args [0] = &iface->byval_arg; - interfaces [j] = mono_class_bind_generic_parameters ( - generic_ienumerator_class, 1, args, FALSE); - /*g_print ("%s implements %s\n", class->name, mono_type_get_name_full (&interfaces [i]->byval_arg, 0));*/ + interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, eclass->interfaces_packed [i]); j ++; } + } else { + interfaces [j++] = inflate_class_one_arg (generic_ienumerator_class, array_class_get_if_rank (valuetype_types [0], original_rank)); } + if (valuetype_types [1]) + interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, array_class_get_if_rank (valuetype_types [1], original_rank)); + } +#if 0 + { + char *type_name = mono_type_get_name_full (&class->byval_arg, 0); + for (i = 0; i < real_count; ++i) { + char *name = mono_type_get_name_full (&interfaces [i]->byval_arg, 0); + g_print ("%s implements %s\n", type_name, name); + g_free (name); } + g_free (type_name); + } +#endif *num = real_count; return interfaces; } @@ -2480,6 +2563,10 @@ mono_class_setup_vtable (MonoClass *class) if (class->vtable) return; + if (mono_debug_using_mono_debugger ()) + /* The debugger currently depends on this */ + mono_class_setup_methods (class); + if (MONO_CLASS_IS_INTERFACE (class)) { /* This sets method->slot for all methods if this is an interface */ mono_class_setup_methods (class); @@ -2554,6 +2641,7 @@ check_core_clr_override_method (MonoClass *class, MonoMethod *override, MonoMeth #define DEBUG_INTERFACE_VTABLE_CODE 0 #define TRACE_INTERFACE_VTABLE_CODE 0 +#define VERIFY_INTERFACE_VTABLE_CODE 0 #if (TRACE_INTERFACE_VTABLE_CODE|DEBUG_INTERFACE_VTABLE_CODE) #define DEBUG_INTERFACE_VTABLE(stmt) do {\ @@ -2571,6 +2659,14 @@ check_core_clr_override_method (MonoClass *class, MonoMethod *override, MonoMeth #define TRACE_INTERFACE_VTABLE(stmt) #endif +#if VERIFY_INTERFACE_VTABLE_CODE +#define VERIFY_INTERFACE_VTABLE(stmt) do {\ + stmt;\ +} while (0) +#else +#define VERIFY_INTERFACE_VTABLE(stmt) +#endif + #if (TRACE_INTERFACE_VTABLE_CODE|DEBUG_INTERFACE_VTABLE_CODE) static char* @@ -2771,6 +2867,60 @@ print_vtable_full (MonoClass *class, MonoMethod** vtable, int size, int first_no } #endif +#if VERIFY_INTERFACE_VTABLE_CODE +static int +mono_method_try_get_vtable_index (MonoMethod *method) +{ + if (method->is_inflated && (method->flags & METHOD_ATTRIBUTE_VIRTUAL)) { + MonoMethodInflated *imethod = (MonoMethodInflated*)method; + if (imethod->declaring->is_generic) + return imethod->declaring->slot; + } + return method->slot; +} + +static void +mono_class_verify_vtable (MonoClass *class) +{ + int i; + char *full_name = mono_type_full_name (&class->byval_arg); + + printf ("*** Verifying VTable of class '%s' \n", full_name); + g_free (full_name); + full_name = NULL; + + if (!class->methods) + return; + + for (i = 0; i < class->method.count; ++i) { + MonoMethod *cm = class->methods [i]; + int slot; + + if (!(cm->flags & METHOD_ATTRIBUTE_VIRTUAL)) + continue; + + g_free (full_name); + full_name = mono_method_full_name (cm, TRUE); + + slot = mono_method_try_get_vtable_index (cm); + if (slot >= 0) { + if (slot >= class->vtable_size) { + printf ("\tInvalid method %s at index %d with vtable of length %d\n", full_name, slot, class->vtable_size); + continue; + } + + if (slot >= 0 && class->vtable [slot] != cm && (class->vtable [slot] && class->vtable [slot]->wrapper_type != MONO_WRAPPER_STATIC_RGCTX_INVOKE)) { + char *other_name = class->vtable [slot] ? mono_method_full_name (class->vtable [slot], TRUE) : g_strdup ("[null value]"); + printf ("\tMethod %s has slot %d but vtable has %s on it\n", full_name, slot, other_name); + g_free (other_name); + } + } else + printf ("\tVirtual method %s does n't have an assigned slot\n", full_name); + } + g_free (full_name); +} +#endif + static void print_unimplemented_interface_method_info (MonoClass *class, MonoClass *ic, MonoMethod *im, int im_slot, MonoMethod **overrides, int onum) { int index; @@ -2843,6 +2993,36 @@ mono_class_setup_vtable_general (MonoClass *class, MonoMethod **overrides, int o max_iid = class->max_interface_id; DEBUG_INTERFACE_VTABLE (first_non_interface_slot = cur_slot); + /* Optimized version for generic instances */ + if (class->generic_class) { + MonoClass *gklass = class->generic_class->container_class; + gboolean usable = TRUE; + + mono_class_setup_vtable (gklass); + for (i = 0; i < gklass->vtable_size; ++i) + if (gklass->vtable [i] && gklass->vtable [i]->wrapper_type == MONO_WRAPPER_STATIC_RGCTX_INVOKE) + usable = FALSE; + + if (usable) { + MonoMethod **tmp = mono_image_alloc0 (class->image, sizeof (gpointer) * gklass->vtable_size); + class->vtable_size = gklass->vtable_size; + for (i = 0; i < gklass->vtable_size; ++i) + if (gklass->vtable [i]) + tmp [i] = mono_class_inflate_generic_method_full (gklass->vtable [i], class, mono_class_get_context (class)); + mono_memory_barrier (); + class->vtable = tmp; + + /* Have to set method->slot for abstract virtual methods */ + if (class->methods && gklass->methods) { + for (i = 0; i < class->method.count; ++i) + if (class->methods [i]->slot == -1) + class->methods [i]->slot = gklass->methods [i]->slot; + } + + return; + } + } + if (class->parent && class->parent->vtable_size) { MonoClass *parent = class->parent; int i; @@ -3178,6 +3358,8 @@ mono_class_setup_vtable_general (MonoClass *class, MonoMethod **overrides, int o } } } + + VERIFY_INTERFACE_VTABLE (mono_class_verify_vtable (class)); } /* @@ -3308,6 +3490,7 @@ generic_array_methods (MonoClass *class) /*g_print ("array generic methods: %d\n", count_generic);*/ generic_array_method_num = count_generic; + g_list_free (list); return generic_array_method_num; } @@ -3475,6 +3658,8 @@ mono_class_init (MonoClass *class) class->field = gklass->field; mono_class_init (gklass); + // FIXME: Why is this needed ? + mono_class_setup_methods (gklass); if (MONO_CLASS_IS_INTERFACE (class)) class->interface_id = mono_get_unique_iid (class); @@ -4109,7 +4294,7 @@ mono_class_create_from_typedef (MonoImage *image, guint32 type_token) if (class->image->assembly_name && !strcmp (class->image->assembly_name, "Mono.Simd") && !strcmp (nspace, "Mono.Simd")) { if (!strncmp (name, "Vector", 6)) - class->simd_type = !strcmp (name + 6, "4f") || !strcmp (name + 6, "4ui") || !strcmp (name + 6, "8us") || !strcmp (name + 6, "16b"); + class->simd_type = !strcmp (name + 6, "2d") || !strcmp (name + 6, "2ul") || !strcmp (name + 6, "2l") || !strcmp (name + 6, "4f") || !strcmp (name + 6, "4ui") || !strcmp (name + 6, "4i") || !strcmp (name + 6, "8s") || !strcmp (name + 6, "8us") || !strcmp (name + 6, "16b") || !strcmp (name + 6, "16sb"); } mono_loader_unlock (); @@ -4248,6 +4433,9 @@ mono_generic_class_get_class (MonoGenericClass *gclass) return klass; } +/* + * LOCKING: Acquires the loader lock. + */ MonoClass * mono_class_from_generic_parameter (MonoGenericParam *param, MonoImage *image, gboolean is_mvar) { @@ -4276,7 +4464,7 @@ mono_class_from_generic_parameter (MonoGenericParam *param, MonoImage *image, gb /* FIXME: */ image = mono_defaults.corlib; - klass = param->pklass = mono_image_alloc0 (image, sizeof (MonoClass)); + klass = mono_image_alloc0 (image, sizeof (MonoClass)); if (param->name) klass->name = param->name; @@ -4347,6 +4535,10 @@ mono_class_from_generic_parameter (MonoGenericParam *param, MonoImage *image, gb mono_class_setup_supertypes (klass); + mono_memory_barrier (); + + param->pklass = klass; + mono_loader_unlock (); mono_profiler_class_loaded (klass, MONO_PROFILE_OK); @@ -4823,7 +5015,7 @@ mono_class_get_field_idx (MonoClass *class, int idx) int i; for (i = 0; i < class->field.count; ++i) - if (class->fields [i].name == name) + if (mono_field_get_name (&class->fields [i]) == name) return &class->fields [i]; g_assert_not_reached (); } else { @@ -4874,7 +5066,7 @@ mono_class_get_field_from_name (MonoClass *klass, const char *name) mono_class_setup_fields_locking (klass); while (klass) { for (i = 0; i < klass->field.count; ++i) { - if (strcmp (name, klass->fields [i].name) == 0) + if (strcmp (name, mono_field_get_name (&klass->fields [i])) == 0) return &klass->fields [i]; } klass = klass->parent; @@ -4915,6 +5107,16 @@ mono_class_get_field_token (MonoClassField *field) return 0; } +static int +mono_field_get_index (MonoClassField *field) +{ + int index = field - field->parent->fields; + + g_assert (index >= 0 && index < field->parent->field.count); + + return index; +} + /* * mono_class_get_field_default_value: * @@ -4925,21 +5127,32 @@ mono_class_get_field_default_value (MonoClassField *field, MonoTypeEnum *def_typ { guint32 cindex; guint32 constant_cols [MONO_CONSTANT_SIZE]; + int field_index; + MonoClass *klass = field->parent; g_assert (field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT); - if (!field->data) { + if (!klass->field_def_values) { + mono_loader_lock (); + if (!klass->field_def_values) + klass->field_def_values = mono_image_alloc0 (klass->image, sizeof (MonoFieldDefaultValue) * klass->field.count); + mono_loader_unlock (); + } + + field_index = mono_field_get_index (field); + + if (!klass->field_def_values [field_index].data) { cindex = mono_metadata_get_constant_index (field->parent->image, mono_class_get_field_token (field), 0); g_assert (cindex); g_assert (!(field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA)); mono_metadata_decode_row (&field->parent->image->tables [MONO_TABLE_CONSTANT], cindex - 1, constant_cols, MONO_CONSTANT_SIZE); - field->def_type = constant_cols [MONO_CONSTANT_TYPE]; - field->data = (gpointer)mono_metadata_blob_heap (field->parent->image, constant_cols [MONO_CONSTANT_VALUE]); + klass->field_def_values [field_index].def_type = constant_cols [MONO_CONSTANT_TYPE]; + klass->field_def_values [field_index].data = (gpointer)mono_metadata_blob_heap (field->parent->image, constant_cols [MONO_CONSTANT_VALUE]); } - *def_type = field->def_type; - return field->data; + *def_type = klass->field_def_values [field_index].def_type; + return klass->field_def_values [field_index].data; } guint32 @@ -6237,6 +6450,8 @@ mono_class_get_fields (MonoClass* klass, gpointer *iter) return NULL; if (!*iter) { mono_class_setup_fields_locking (klass); + if (klass->exception_type) + return NULL; /* start from the first */ if (klass->field.count) { return *iter = &klass->fields [0]; @@ -6293,13 +6508,20 @@ mono_class_get_methods (MonoClass* klass, gpointer *iter) return NULL; } +/* + * mono_class_get_virtual_methods: + * + * Iterate over the virtual methods of KLASS. + * + * LOCKING: Assumes the loader lock is held (because of the klass->methods check). + */ static MonoMethod* mono_class_get_virtual_methods (MonoClass* klass, gpointer *iter) { MonoMethod** method; if (!iter) return NULL; - if (klass->methods || !MONO_CLASS_HAS_STATIC_METADATA (klass)) { + if (klass->methods || !MONO_CLASS_HAS_STATIC_METADATA (klass) || mono_debug_using_mono_debugger ()) { if (!*iter) { mono_class_setup_methods (klass); /* start from the first */ @@ -6592,6 +6814,34 @@ mono_field_get_offset (MonoClassField *field) return field->offset; } +static const char * +mono_field_get_rva (MonoClassField *field) +{ + guint32 rva; + int field_index; + MonoClass *klass = field->parent; + + g_assert (field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA); + + if (!klass->field_def_values) { + mono_loader_lock (); + if (!klass->field_def_values) + klass->field_def_values = mono_image_alloc0 (klass->image, sizeof (MonoFieldDefaultValue) * klass->field.count); + mono_loader_unlock (); + } + + field_index = mono_field_get_index (field); + + if (!klass->field_def_values [field_index].data && !klass->image->dynamic) { + mono_metadata_field_info (field->parent->image, klass->field.first + field_index, NULL, &rva, NULL); + if (!rva) + g_warning ("field %s in %s should have RVA data, but hasn't", mono_field_get_name (field), field->parent->name); + klass->field_def_values [field_index].data = mono_image_rva_map (field->parent->image, rva); + } + + return klass->field_def_values [field_index].data; +} + /** * mono_field_get_data; * @field: the MonoClassField to act on @@ -6600,14 +6850,16 @@ mono_field_get_offset (MonoClassField *field) * data if it has an RVA flag. */ const char * -mono_field_get_data (MonoClassField *field) +mono_field_get_data (MonoClassField *field) { if (field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT) { MonoTypeEnum def_type; return mono_class_get_field_default_value (field, &def_type); + } else if (field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) { + return mono_field_get_rva (field); } else { - return field->data; + return NULL; } } @@ -7005,7 +7257,7 @@ mono_class_get_generic_type_definition (MonoClass *klass) * * Visibility checks ignoring generic instantiations. */ -static gboolean +gboolean mono_class_has_parent_and_ignore_generics (MonoClass *klass, MonoClass *parent) { int i; @@ -7406,7 +7658,7 @@ mono_generic_class_is_generic_type_definition (MonoGenericClass *gklass) gboolean mono_class_generic_sharing_enabled (MonoClass *class) { -#if defined(__i386__) || defined(__x86_64__) || defined(__arm__) || defined(__ppc__) || defined(__powerpc__) +#if defined(__i386__) || defined(__x86_64__) || defined(__arm__) || defined(__mono_ppc__) static gboolean supported = TRUE; #else /* Not supported by the JIT backends */ @@ -7459,3 +7711,19 @@ mono_class_generic_sharing_enabled (MonoClass *class) g_assert_not_reached (); } } + +/* + * mono_class_setup_interface_id: + * + * Initializes MonoClass::interface_id if required. + * + * LOCKING: Acquires the loader lock. + */ +void +mono_class_setup_interface_id (MonoClass *class) +{ + mono_loader_lock (); + if (MONO_CLASS_IS_INTERFACE (class) && !class->interface_id) + class->interface_id = mono_get_unique_iid (class); + mono_loader_unlock (); +}