X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mono%2Fmetadata%2Fclass.c;h=701f10dbc638225cb1cdd15145f31896d8c25ee0;hb=b196696d61725b6fa5d0a5a31df5659e98b8b729;hp=0caf11adc7c0efc67dc447ae485cf7053b2b4b24;hpb=cdbafe6f46338be0ae6617c0219888eac826b4df;p=mono.git diff --git a/mono/metadata/class.c b/mono/metadata/class.c index 0caf11adc7c..701f10dbc63 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 @@ -49,6 +52,10 @@ gboolean mono_print_vtable = FALSE; */ gboolean mono_setup_vtable_in_class_init = TRUE; +/* Statistics */ +guint32 inflated_classes, inflated_classes_size, inflated_methods_size; +guint32 classes_size, class_ext_size; + /* Function supplied by the runtime to find classes by name using information from the AOT file */ static MonoGetClassFromName get_class_from_name = NULL; @@ -115,9 +122,9 @@ mono_class_from_typeref (MonoImage *image, guint32 type_token) MonoClass *enclosing = mono_class_from_typeref (image, MONO_TOKEN_TYPE_REF | idx); GList *tmp; - if (enclosing->nested_classes_inited) { + if (enclosing->nested_classes_inited && enclosing->ext) { /* Micro-optimization: don't scan the metadata tables if enclosing is already inited */ - for (tmp = enclosing->nested_classes; tmp; tmp = tmp->next) { + for (tmp = enclosing->ext->nested_classes; tmp; tmp = tmp->next) { res = tmp->data; if (strcmp (res->name, name) == 0) return res; @@ -165,25 +172,23 @@ mono_class_from_typeref (MonoImage *image, guint32 type_token) static void * -mono_mempool_dup (MonoMemPool *mp, void *data, guint size) +mono_image_memdup (MonoImage *image, void *data, guint size) { - void *res = mono_mempool_alloc (mp, size); + void *res = mono_image_alloc (image, size); memcpy (res, data, size); return res; } /* Copy everything mono_metadata_free_array free. */ MonoArrayType * -mono_dup_array_type (MonoMemPool *mp, MonoArrayType *a) +mono_dup_array_type (MonoImage *image, MonoArrayType *a) { - if (mp) { - mono_loader_lock (); - a = mono_mempool_dup (mp, a, sizeof (MonoArrayType)); + if (image) { + a = mono_image_memdup (image, a, sizeof (MonoArrayType)); if (a->sizes) - a->sizes = mono_mempool_dup (mp, a->sizes, a->numsizes * sizeof (int)); + a->sizes = mono_image_memdup (image, a->sizes, a->numsizes * sizeof (int)); if (a->lobounds) - a->lobounds = mono_mempool_dup (mp, a->lobounds, a->numlobounds * sizeof (int)); - mono_loader_unlock (); + a->lobounds = mono_image_memdup (image, a->lobounds, a->numlobounds * sizeof (int)); } else { a = g_memdup (a, sizeof (MonoArrayType)); if (a->sizes) @@ -196,15 +201,15 @@ mono_dup_array_type (MonoMemPool *mp, MonoArrayType *a) /* Copy everything mono_metadata_free_method_signature free. */ MonoMethodSignature* -mono_metadata_signature_deep_dup (MonoMemPool *mp, MonoMethodSignature *sig) +mono_metadata_signature_deep_dup (MonoImage *image, MonoMethodSignature *sig) { int i; - sig = mono_metadata_signature_dup_full (mp, sig); + sig = mono_metadata_signature_dup_full (image, sig); - sig->ret = mono_metadata_type_dup (mp, sig->ret); + sig->ret = mono_metadata_type_dup (image, sig->ret); for (i = 0; i < sig->param_count; ++i) - sig->params [i] = mono_metadata_type_dup (mp, sig->params [i]); + sig->params [i] = mono_metadata_type_dup (image, sig->params [i]); return sig; } @@ -363,7 +368,7 @@ mono_type_get_name_recurse (MonoType *type, GString *str, gboolean is_recursed, for (i = 0; i < klass->generic_container->type_argc; i++) { if (i) g_string_append_c (str, ','); - g_string_append (str, klass->generic_container->type_params [i].name); + g_string_append (str, mono_generic_container_get_param (klass->generic_container, i)->name); } if (format == MONO_TYPE_NAME_FORMAT_IL) g_string_append_c (str, '>'); @@ -447,9 +452,9 @@ MonoType* mono_type_get_underlying_type (MonoType *type) { if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype && !type->byref) - return type->data.klass->enum_basetype; + return mono_class_enum_basetype (type->data.klass); if (type->type == MONO_TYPE_GENERICINST && type->data.generic_class->container_class->enumtype && !type->byref) - return type->data.generic_class->container_class->enum_basetype; + return mono_class_enum_basetype (type->data.generic_class->container_class); return type; } @@ -482,12 +487,12 @@ mono_class_is_open_constructed_type (MonoType *t) } static MonoType* -inflate_generic_type (MonoMemPool *mempool, MonoType *type, MonoGenericContext *context) +inflate_generic_type (MonoImage *image, MonoType *type, MonoGenericContext *context) { switch (type->type) { case MONO_TYPE_MVAR: { MonoType *nt; - int num = type->data.generic_param->num; + int num = mono_type_get_generic_param_num (type); MonoGenericInst *inst = context->method_inst; if (!inst || !inst->type_argv) return NULL; @@ -499,20 +504,20 @@ inflate_generic_type (MonoMemPool *mempool, MonoType *type, MonoGenericContext * * while the VAR/MVAR duplicates a type from the context. So, we need to ensure that the * ->byref and ->attrs from @type are propagated to the returned type. */ - nt = mono_metadata_type_dup (mempool, inst->type_argv [num]); + nt = mono_metadata_type_dup (image, inst->type_argv [num]); nt->byref = type->byref; nt->attrs = type->attrs; return nt; } case MONO_TYPE_VAR: { MonoType *nt; - int num = type->data.generic_param->num; + int num = mono_type_get_generic_param_num (type); MonoGenericInst *inst = context->class_inst; if (!inst) return NULL; if (num >= inst->type_argc) g_error ("VAR %d (%s) cannot be expanded in this context with %d instantiations", num, type->data.generic_param->name, inst->type_argc); - nt = mono_metadata_type_dup (mempool, inst->type_argv [num]); + nt = mono_metadata_type_dup (image, inst->type_argv [num]); nt->byref = type->byref; nt->attrs = type->attrs; return nt; @@ -522,7 +527,7 @@ inflate_generic_type (MonoMemPool *mempool, MonoType *type, MonoGenericContext * MonoType *nt, *inflated = inflate_generic_type (NULL, &eclass->byval_arg, context); if (!inflated) return NULL; - nt = mono_metadata_type_dup (mempool, type); + nt = mono_metadata_type_dup (image, type); nt->data.klass = mono_class_from_mono_type (inflated); mono_metadata_free_type (inflated); return nt; @@ -532,7 +537,7 @@ inflate_generic_type (MonoMemPool *mempool, MonoType *type, MonoGenericContext * MonoType *nt, *inflated = inflate_generic_type (NULL, &eclass->byval_arg, context); if (!inflated) return NULL; - nt = mono_metadata_type_dup (mempool, type); + nt = mono_metadata_type_dup (image, type); nt->data.array = g_memdup (nt->data.array, sizeof (MonoArrayType)); nt->data.array->eklass = mono_class_from_mono_type (inflated); mono_metadata_free_type (inflated); @@ -552,7 +557,7 @@ inflate_generic_type (MonoMemPool *mempool, MonoType *type, MonoGenericContext * if (gclass == type->data.generic_class) return NULL; - nt = mono_metadata_type_dup (mempool, type); + nt = mono_metadata_type_dup (image, type); nt->data.generic_class = gclass; return nt; } @@ -574,7 +579,7 @@ inflate_generic_type (MonoMemPool *mempool, MonoType *type, MonoGenericContext * gclass = mono_metadata_lookup_generic_class (klass, inst, klass->image->dynamic); - nt = mono_metadata_type_dup (mempool, type); + nt = mono_metadata_type_dup (image, type); nt->type = MONO_TYPE_GENERICINST; nt->data.generic_class = gclass; return nt; @@ -597,6 +602,32 @@ mono_class_get_context (MonoClass *class) return class->generic_class ? mono_generic_class_get_context (class->generic_class) : NULL; } +/* + * mono_class_get_generic_container: + * + * Return the generic container of KLASS which should be a generic type definition. + */ +MonoGenericContainer* +mono_class_get_generic_container (MonoClass *klass) +{ + g_assert (klass->is_generic); + + return klass->generic_container; +} + +/* + * mono_class_get_generic_class: + * + * Return the MonoGenericClass of KLASS, which should be a generic instance. + */ +MonoGenericClass* +mono_class_get_generic_class (MonoClass *klass) +{ + g_assert (klass->is_inflated); + + return klass->generic_class; +} + /* * mono_class_inflate_generic_type_with_mempool: * @mempool: a mempool @@ -610,12 +641,12 @@ mono_class_get_context (MonoClass *class) * 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) +mono_class_inflate_generic_type_with_mempool (MonoImage *image, MonoType *type, MonoGenericContext *context) { MonoType *inflated = NULL; if (context) - inflated = inflate_generic_type (mempool, type, context); + inflated = inflate_generic_type (image, type, context); if (!inflated) { MonoType *shared = mono_metadata_get_shared_type (type); @@ -623,7 +654,7 @@ mono_class_inflate_generic_type_with_mempool (MonoMemPool *mempool, MonoType *ty if (shared) { return shared; } else { - return mono_metadata_type_dup (mempool, type); + return mono_metadata_type_dup (image, type); } } @@ -649,18 +680,18 @@ mono_class_inflate_generic_type (MonoType *type, MonoGenericContext *context) } /* - * mono_class_inflate_generic_type_with_mempool_no_copy: + * mono_class_inflate_generic_type_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) +mono_class_inflate_generic_type_no_copy (MonoImage *image, MonoType *type, MonoGenericContext *context) { MonoType *inflated = NULL; if (context) - inflated = inflate_generic_type (mempool, type, context); + inflated = inflate_generic_type (image, type, context); if (!inflated) return type; @@ -669,6 +700,25 @@ mono_class_inflate_generic_type_with_mempool_no_copy (MonoMemPool *mempool, Mono return inflated; } +/* + * mono_class_inflate_generic_class: + * + * Inflate the class GKLASS with CONTEXT. + */ +MonoClass* +mono_class_inflate_generic_class (MonoClass *gklass, MonoGenericContext *context) +{ + MonoClass *res; + MonoType *inflated; + + inflated = mono_class_inflate_generic_type (&gklass->byval_arg, context); + + res = mono_class_from_mono_type (inflated); + mono_metadata_free_type (inflated); + + return res; +} + static MonoGenericContext inflate_generic_context (MonoGenericContext *context, MonoGenericContext *inflate_with) { @@ -773,7 +823,7 @@ mono_class_inflate_generic_method_full (MonoMethod *method, MonoClass *klass_hin iresult = g_new0 (MonoMethodInflated, 1); iresult->context = *context; iresult->declaring = method; - iresult->is_mb_open = is_mb_open; + iresult->method.method.is_mb_open = is_mb_open; if (!context->method_inst && method->is_generic) iresult->context.method_inst = mono_method_get_generic_container (method)->context.method_inst; @@ -796,6 +846,8 @@ mono_class_inflate_generic_method_full (MonoMethod *method, MonoClass *klass_hin mono_stats.inflated_method_count++; + inflated_methods_size += sizeof (MonoMethodInflated); + sig = mono_method_signature (method); if (sig->pinvoke) { memcpy (&iresult->method.pinvoke, method, sizeof (MonoMethodPInvoke)); @@ -808,6 +860,7 @@ mono_class_inflate_generic_method_full (MonoMethod *method, MonoClass *klass_hin result->is_inflated = TRUE; result->is_generic = FALSE; result->signature = NULL; + result->is_mb_open = is_mb_open; if (!context->method_inst) { /* Set the generic_container of the result to the generic_container of method */ @@ -850,14 +903,43 @@ mono_get_inflated_method (MonoMethod *method) return method; } +/* + * mono_method_get_context_general: + * @method: a method + * @uninflated: handle uninflated methods? + * + * Returns the generic context of a method or NULL if it doesn't have + * one. For an inflated method that's the context stored in the + * method. Otherwise it's in the method's generic container or in the + * generic container of the method's class. + */ MonoGenericContext* -mono_method_get_context (MonoMethod *method) +mono_method_get_context_general (MonoMethod *method, gboolean uninflated) { - MonoMethodInflated *imethod; - if (!method->is_inflated) + if (method->is_inflated) { + MonoMethodInflated *imethod = (MonoMethodInflated *) method; + return &imethod->context; + } + if (!uninflated) return NULL; - imethod = (MonoMethodInflated *) method; - return &imethod->context; + if (method->is_generic) + return &(mono_method_get_generic_container (method)->context); + if (method->klass->generic_container) + return &method->klass->generic_container->context; + return NULL; +} + +/* + * mono_method_get_context: + * @method: a method + * + * Returns the generic context for method if it's inflated, otherwise + * NULL. + */ +MonoGenericContext* +mono_method_get_context (MonoMethod *method) +{ + return mono_method_get_context_general (method, FALSE); } /* @@ -875,9 +957,7 @@ mono_method_get_generic_container (MonoMethod *method) if (!method->is_generic) return NULL; - mono_loader_lock (); - container = mono_property_hash_lookup (method->klass->image->property_hash, method, MONO_METHOD_PROP_GENERIC_CONTAINER); - mono_loader_unlock (); + container = mono_image_property_lookup (method->klass->image, method, MONO_METHOD_PROP_GENERIC_CONTAINER); g_assert (container); return container; @@ -894,9 +974,7 @@ mono_method_set_generic_container (MonoMethod *method, MonoGenericContainer* con { g_assert (method->is_generic); - mono_loader_lock (); - mono_property_hash_insert (method->klass->image->property_hash, method, MONO_METHOD_PROP_GENERIC_CONTAINER, container); - mono_loader_unlock (); + mono_image_property_insert (method->klass->image, method, MONO_METHOD_PROP_GENERIC_CONTAINER, container); } /** @@ -1073,7 +1151,7 @@ mono_class_setup_fields (MonoClass *class) 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_no_copy (class->image->mempool, gfield->type, mono_class_get_context (class)); + field->type = mono_class_inflate_generic_type_no_copy (class->image, gfield->type, mono_class_get_context (class)); g_assert (field->type->attrs == gfield->type->attrs); if (mono_field_is_deleted (field)) continue; @@ -1121,8 +1199,7 @@ mono_class_setup_fields (MonoClass *class) } if (class->enumtype && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) { - class->enum_basetype = field->type; - class->cast_class = class->element_class = mono_class_from_mono_type (class->enum_basetype); + class->cast_class = class->element_class = mono_class_from_mono_type (field->type); blittable = class->element_class->blittable; } @@ -1134,7 +1211,7 @@ mono_class_setup_fields (MonoClass *class) class->blittable = blittable; - if (class->enumtype && !class->enum_basetype) { + if (class->enumtype && !mono_class_enum_basetype (class)) { if (!((strcmp (class->name, "Enum") == 0) && (strcmp (class->name_space, "System") == 0))) G_BREAKPOINT (); } @@ -1526,6 +1603,8 @@ mono_class_setup_methods (MonoClass *class) class->method.count = 3 + (class->rank > 1? 2: 1); + mono_class_setup_interfaces (class); + if (class->interface_count) { count_generic = generic_array_methods (class); first_generic = class->method.count; @@ -1676,12 +1755,7 @@ mono_class_get_inflated_method (MonoClass *class, MonoMethod *method) MonoMethod* mono_class_get_vtable_entry (MonoClass *class, int offset) { - if (class->generic_class) { - MonoClass *gklass = class->generic_class->container_class; - mono_class_setup_vtable (gklass); - if (gklass->vtable [offset]->wrapper_type != MONO_WRAPPER_STATIC_RGCTX_INVOKE) - return mono_class_inflate_generic_method_full (gklass->vtable [offset], class, mono_class_get_context (class)); - } + MonoMethod *m; if (class->rank == 1) { /* @@ -1693,8 +1767,24 @@ mono_class_get_vtable_entry (MonoClass *class, int offset) return class->parent->vtable [offset]; } - mono_class_setup_vtable (class); - return class->vtable [offset]; + if (class->generic_class) { + MonoClass *gklass = class->generic_class->container_class; + mono_class_setup_vtable (gklass); + m = gklass->vtable [offset]; + + m = mono_class_inflate_generic_method_full (m, class, mono_class_get_context (class)); + } else { + mono_class_setup_vtable (class); + m = class->vtable [offset]; + } + + /* + * We have to add static rgctx wrappers somewhere, we do it here, + * altough it should probably be done by the JIT. + */ + if (mono_method_needs_static_rgctx_invoke (m, FALSE)) + m = mono_marshal_get_static_rgctx_invoke (m); + return m; } static void @@ -1706,30 +1796,32 @@ mono_class_setup_properties (MonoClass *class) MonoProperty *properties; guint32 last; - if (class->properties) + if (class->ext && class->ext->properties) return; mono_loader_lock (); - if (class->properties) { + if (class->ext && class->ext->properties) { mono_loader_unlock (); return; } + mono_class_alloc_ext (class); + if (class->generic_class) { MonoClass *gklass = class->generic_class->container_class; mono_class_init (gklass); mono_class_setup_properties (gklass); - class->property = gklass->property; + class->ext->property = gklass->ext->property; - properties = g_new0 (MonoProperty, class->property.count + 1); + properties = g_new0 (MonoProperty, class->ext->property.count + 1); - for (i = 0; i < class->property.count; i++) { + for (i = 0; i < class->ext->property.count; i++) { MonoProperty *prop = &properties [i]; - *prop = gklass->properties [i]; + *prop = gklass->ext->properties [i]; if (prop->get) prop->get = mono_class_inflate_generic_method_full ( @@ -1741,18 +1833,18 @@ mono_class_setup_properties (MonoClass *class) prop->parent = class; } } else { - class->property.first = mono_metadata_properties_from_typedef (class->image, mono_metadata_token_index (class->type_token) - 1, &last); - class->property.count = last - class->property.first; + class->ext->property.first = mono_metadata_properties_from_typedef (class->image, mono_metadata_token_index (class->type_token) - 1, &last); + class->ext->property.count = last - class->ext->property.first; - if (class->property.count) + if (class->ext->property.count) mono_class_setup_methods (class); - properties = mono_image_alloc0 (class->image, sizeof (MonoProperty) * class->property.count); - for (i = class->property.first; i < last; ++i) { + properties = mono_image_alloc0 (class->image, sizeof (MonoProperty) * class->ext->property.count); + for (i = class->ext->property.first; i < last; ++i) { mono_metadata_decode_table_row (class->image, MONO_TABLE_PROPERTY, i, cols, MONO_PROPERTY_SIZE); - properties [i - class->property.first].parent = class; - properties [i - class->property.first].attrs = cols [MONO_PROPERTY_FLAGS]; - properties [i - class->property.first].name = mono_metadata_string_heap (class->image, cols [MONO_PROPERTY_NAME]); + properties [i - class->ext->property.first].parent = class; + properties [i - class->ext->property.first].attrs = cols [MONO_PROPERTY_FLAGS]; + properties [i - class->ext->property.first].name = mono_metadata_string_heap (class->image, cols [MONO_PROPERTY_NAME]); startm = mono_metadata_methods_from_property (class->image, i, &endm); for (j = startm; j < endm; ++j) { @@ -1768,10 +1860,10 @@ mono_class_setup_properties (MonoClass *class) switch (cols [MONO_METHOD_SEMA_SEMANTICS]) { case METHOD_SEMANTIC_SETTER: - properties [i - class->property.first].set = method; + properties [i - class->ext->property.first].set = method; break; case METHOD_SEMANTIC_GETTER: - properties [i - class->property.first].get = method; + properties [i - class->ext->property.first].get = method; break; default: break; @@ -1783,7 +1875,7 @@ mono_class_setup_properties (MonoClass *class) mono_memory_barrier (); /* Leave this assignment as the last op in the function */ - class->properties = properties; + class->ext->properties = properties; mono_loader_unlock (); } @@ -1814,31 +1906,33 @@ mono_class_setup_events (MonoClass *class) guint32 last; MonoEvent *events; - if (class->events) + if (class->ext && class->ext->events) return; mono_loader_lock (); - if (class->events) { + if (class->ext && class->ext->events) { mono_loader_unlock (); return; } + mono_class_alloc_ext (class); + if (class->generic_class) { MonoClass *gklass = class->generic_class->container_class; MonoGenericContext *context; mono_class_setup_events (gklass); - class->event = gklass->event; + class->ext->event = gklass->ext->event; - class->events = g_new0 (MonoEvent, class->event.count); + class->ext->events = g_new0 (MonoEvent, class->ext->event.count); - if (class->event.count) + if (class->ext->event.count) context = mono_class_get_context (class); - for (i = 0; i < class->event.count; i++) { - MonoEvent *event = &class->events [i]; - MonoEvent *gevent = &gklass->events [i]; + for (i = 0; i < class->ext->event.count; i++) { + MonoEvent *event = &class->ext->events [i]; + MonoEvent *gevent = &gklass->ext->events [i]; event->parent = class; event->name = gevent->name; @@ -1853,15 +1947,15 @@ mono_class_setup_events (MonoClass *class) return; } - class->event.first = mono_metadata_events_from_typedef (class->image, mono_metadata_token_index (class->type_token) - 1, &last); - class->event.count = last - class->event.first; + class->ext->event.first = mono_metadata_events_from_typedef (class->image, mono_metadata_token_index (class->type_token) - 1, &last); + class->ext->event.count = last - class->ext->event.first; - if (class->event.count) + if (class->ext->event.count) mono_class_setup_methods (class); - events = mono_image_alloc0 (class->image, sizeof (MonoEvent) * class->event.count); - for (i = class->event.first; i < last; ++i) { - MonoEvent *event = &events [i - class->event.first]; + events = mono_image_alloc0 (class->image, sizeof (MonoEvent) * class->ext->event.count); + for (i = class->ext->event.first; i < last; ++i) { + MonoEvent *event = &events [i - class->ext->event.first]; mono_metadata_decode_table_row (class->image, MONO_TABLE_EVENT, i, cols, MONO_EVENT_SIZE); event->parent = class; @@ -1914,7 +2008,7 @@ mono_class_setup_events (MonoClass *class) mono_memory_barrier (); /* Leave this assignment as the last op in the function */ - class->events = events; + class->ext->events = events; mono_loader_unlock (); } @@ -2004,6 +2098,8 @@ collect_implemented_interfaces_aux (MonoClass *klass, GPtrArray **res) { int i; MonoClass *ic; + + mono_class_setup_interfaces (klass); for (i = 0; i < klass->interface_count; i++) { ic = klass->interfaces [i]; @@ -2095,9 +2191,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 && mono_class_enum_basetype (eclass)) + valuetype_types [1] = mono_class_from_mono_type (mono_class_enum_basetype (eclass)); +} + /* 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) @@ -2106,9 +2250,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; @@ -2119,12 +2263,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; @@ -2159,32 +2305,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; @@ -2201,11 +2336,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; @@ -2229,59 +2372,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; } @@ -2477,7 +2619,13 @@ setup_interface_offsets (MonoClass *class, int cur_slot) } /* - * Setup interface offsets for interfaces. Used by Ref.Emit. + * Setup interface offsets for interfaces. + * Initializes: + * - class->max_interface_id + * - class->interface_offsets_count + * - class->interfaces_packed + * - class->interface_offsets_packed + * - class->interface_bitmap */ void mono_class_setup_interface_offsets (MonoClass *class) @@ -2579,17 +2727,6 @@ mono_class_setup_vtable (MonoClass *class) return; } -static void -check_core_clr_override_method (MonoClass *class, MonoMethod *override, MonoMethod *base) -{ - MonoSecurityCoreCLRLevel override_level = mono_security_core_clr_method_level (override, FALSE); - MonoSecurityCoreCLRLevel base_level = mono_security_core_clr_method_level (base, FALSE); - - if (override_level != base_level && base_level == MONO_SECURITY_CORE_CLR_CRITICAL) - mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL); -} - - #define DEBUG_INTERFACE_VTABLE_CODE 0 #define TRACE_INTERFACE_VTABLE_CODE 0 #define VERIFY_INTERFACE_VTABLE_CODE 0 @@ -2688,7 +2825,7 @@ check_interface_method_override (MonoClass *class, MonoMethod *im, MonoMethod *c } if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR) - check_core_clr_override_method (class, cm, im); + mono_security_core_clr_check_override (class, cm, im); TRACE_INTERFACE_VTABLE (printf ("[NAME CHECK OK]")); return TRUE; } else { @@ -2757,7 +2894,7 @@ check_interface_method_override (MonoClass *class, MonoMethod *im, MonoMethod *c } if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR) - check_core_clr_override_method (class, cm, im); + mono_security_core_clr_check_override (class, cm, im); TRACE_INTERFACE_VTABLE (printf ("[INJECTED INTERFACE CHECK OK]")); return TRUE; @@ -2860,7 +2997,7 @@ mono_class_verify_vtable (MonoClass *class) continue; } - if (slot >= 0 && class->vtable [slot] != cm && (class->vtable [slot] && class->vtable [slot]->wrapper_type != MONO_WRAPPER_STATIC_RGCTX_INVOKE)) { + if (slot >= 0 && class->vtable [slot] != cm && (class->vtable [slot])) { 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); @@ -2947,24 +3084,28 @@ mono_class_setup_vtable_general (MonoClass *class, MonoMethod **overrides, int o /* Optimized version for generic instances */ if (class->generic_class) { MonoClass *gklass = class->generic_class->container_class; - gboolean usable = TRUE; + MonoMethod **tmp; mono_class_setup_vtable (gklass); + + 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] && 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; + if (gklass->vtable [i]) { + tmp [i] = mono_class_inflate_generic_method_full (gklass->vtable [i], class, mono_class_get_context (class)); + tmp [i]->slot = gklass->vtable [i]->slot; + } + mono_memory_barrier (); + class->vtable = tmp; - return; + /* 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) { @@ -3013,7 +3154,7 @@ mono_class_setup_vtable_general (MonoClass *class, MonoMethod **overrides, int o g_hash_table_insert (override_map, overrides [i * 2], overrides [i * 2 + 1]); if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR) - check_core_clr_override_method (class, vtable [dslot], decl); + mono_security_core_clr_check_override (class, vtable [dslot], decl); } } TRACE_INTERFACE_VTABLE (print_overrides (override_map, "AFTER OVERRIDING INTERFACE METHODS")); @@ -3169,7 +3310,7 @@ mono_class_setup_vtable_general (MonoClass *class, MonoMethod **overrides, int o } if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR) - check_core_clr_override_method (class, cm, m1); + mono_security_core_clr_check_override (class, cm, m1); slot = mono_method_get_vtable_slot (m1); g_assert (cm->slot < max_vtsize); @@ -3205,7 +3346,7 @@ mono_class_setup_vtable_general (MonoClass *class, MonoMethod **overrides, int o g_hash_table_insert (override_map, decl, overrides [i * 2 + 1]); if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR) - check_core_clr_override_method (class, vtable [decl->slot], decl); + mono_security_core_clr_check_override (class, vtable [decl->slot], decl); } } @@ -3237,15 +3378,6 @@ mono_class_setup_vtable_general (MonoClass *class, MonoMethod **overrides, int o class->vtable_size = cur_slot; } - /* FIXME: only do this if the class is actually sharable */ - if (class->valuetype && (class->generic_class || class->generic_container) && - mono_class_generic_sharing_enabled (class)) { - for (i = 0; i < max_vtsize; ++i) { - if (vtable [i] && vtable [i]->wrapper_type == MONO_WRAPPER_NONE) - vtable [i] = mono_marshal_get_static_rgctx_invoke (vtable [i]); - } - } - /* Try to share the vtable with our parent. */ if (class->parent && (class->parent->vtable_size == class->vtable_size) && (memcmp (class->parent->vtable, vtable, sizeof (gpointer) * class->vtable_size) == 0)) { mono_memory_barrier (); @@ -3371,16 +3503,6 @@ initialize_object_slots (MonoClass *class) } } -static GList* -g_list_prepend_mempool (GList* l, MonoMemPool* mp, gpointer datum) -{ - GList* n = mono_mempool_alloc (mp, sizeof (GList)); - n->next = l; - n->prev = NULL; - n->data = datum; - return n; -} - typedef struct { MonoMethod *array_method; char *name; @@ -3523,22 +3645,6 @@ set_failure_from_loader_error (MonoClass *class, MonoLoaderError *error) mono_class_set_failure (class, error->exception_type, exception_data); } -static void -check_core_clr_inheritance (MonoClass *class) -{ - MonoSecurityCoreCLRLevel class_level, parent_level; - MonoClass *parent = class->parent; - - if (!parent) - return; - - class_level = mono_security_core_clr_class_level (class); - parent_level = mono_security_core_clr_class_level (parent); - - if (class_level < parent_level) - mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL); -} - /** * mono_class_init: * @class: the class to initialize @@ -3589,7 +3695,7 @@ mono_class_init (MonoClass *class) } if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR) - check_core_clr_inheritance (class); + mono_security_core_clr_check_inheritance (class); mono_stats.initialized_class_count++; @@ -3607,8 +3713,6 @@ mono_class_init (MonoClass *class) if (MONO_CLASS_IS_INTERFACE (class)) class->interface_id = mono_get_unique_iid (class); - - g_assert (class->interface_count == gklass->interface_count); } if (class->parent && !class->parent->inited) @@ -4132,18 +4236,31 @@ mono_class_create_from_typedef (MonoImage *image, guint32 type_token) mono_internal_hash_table_insert (&image->class_cache, GUINT_TO_POINTER (type_token), class); + classes_size += sizeof (MonoClass); + /* * Check whether we're a generic type definition. */ class->generic_container = mono_metadata_load_generic_params (image, class->type_token, NULL); if (class->generic_container) { + class->is_generic = 1; class->generic_container->owner.klass = class; context = &class->generic_container->context; } if (cols [MONO_TYPEDEF_EXTENDS]) { - parent = mono_class_get_full ( - image, mono_metadata_token_from_dor (cols [MONO_TYPEDEF_EXTENDS]), context); + guint32 parent_token = mono_metadata_token_from_dor (cols [MONO_TYPEDEF_EXTENDS]); + + if (mono_metadata_token_table (parent_token) == MONO_TABLE_TYPESPEC) { + /*WARNING: this must satisfy mono_metadata_type_hash*/ + class->this_arg.byref = 1; + class->this_arg.data.klass = class; + class->this_arg.type = MONO_TYPE_CLASS; + class->byval_arg.data.klass = class; + class->byval_arg.type = MONO_TYPE_CLASS; + } + parent = mono_class_get_full (image, parent_token, context); + if (parent == NULL){ mono_internal_hash_table_remove (&image->class_cache, GUINT_TO_POINTER (type_token)); mono_loader_unlock (); @@ -4171,6 +4288,7 @@ mono_class_create_from_typedef (MonoImage *image, guint32 type_token) class->interfaces = interfaces; class->interface_count = icount; + class->interfaces_inited = 1; } if ((class->flags & TYPE_ATTRIBUTE_STRING_FORMAT_MASK) == TYPE_ATTRIBUTE_UNICODE_CLASS) @@ -4218,13 +4336,13 @@ mono_class_create_from_typedef (MonoImage *image, guint32 type_token) } if (class->enumtype) { - class->enum_basetype = mono_class_find_enum_basetype (class); - if (!class->enum_basetype) { + MonoType *enum_basetype = mono_class_find_enum_basetype (class); + if (!enum_basetype) { mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL); mono_loader_unlock (); return NULL; } - class->cast_class = class->element_class = mono_class_from_mono_type (class->enum_basetype); + class->cast_class = class->element_class = mono_class_from_mono_type (enum_basetype); } /* @@ -4273,7 +4391,6 @@ MonoClass* mono_generic_class_get_class (MonoGenericClass *gclass) { MonoClass *klass, *gklass; - int i; mono_loader_lock (); if (gclass->cached_class) { @@ -4292,10 +4409,8 @@ mono_generic_class_get_class (MonoGenericClass *gclass) * nesting context should have, but it may also have additional * generic parameters... */ - MonoType *inflated = mono_class_inflate_generic_type ( - &gklass->nested_in->byval_arg, mono_generic_class_get_context (gclass)); - klass->nested_in = mono_class_from_mono_type (inflated); - mono_metadata_free_type (inflated); + klass->nested_in = mono_class_inflate_generic_class (gklass->nested_in, + mono_generic_class_get_context (gclass)); } klass->name = gklass->name; @@ -4307,8 +4422,8 @@ mono_generic_class_get_class (MonoGenericClass *gclass) klass->flags = gklass->flags; klass->type_token = gklass->type_token; klass->field.count = gklass->field.count; - klass->property.count = gklass->property.count; + klass->is_inflated = 1; klass->generic_class = gclass; klass->this_arg.type = klass->byval_arg.type = MONO_TYPE_GENERICINST; @@ -4322,35 +4437,21 @@ mono_generic_class_get_class (MonoGenericClass *gclass) if (mono_class_is_nullable (klass)) klass->cast_class = klass->element_class = mono_class_get_nullable_param (klass); - klass->interface_count = gklass->interface_count; - klass->interfaces = g_new0 (MonoClass *, klass->interface_count); - for (i = 0; i < klass->interface_count; i++) { - MonoType *it = &gklass->interfaces [i]->byval_arg; - MonoType *inflated = mono_class_inflate_generic_type (it, mono_generic_class_get_context (gclass)); - klass->interfaces [i] = mono_class_from_mono_type (inflated); - mono_metadata_free_type (inflated); - } - /* * We're not interested in the nested classes of a generic instance. * We use the generic type definition to look for nested classes. */ - klass->nested_classes = NULL; if (gklass->parent) { - MonoType *inflated = mono_class_inflate_generic_type ( - &gklass->parent->byval_arg, mono_generic_class_get_context (gclass)); - - klass->parent = mono_class_from_mono_type (inflated); - mono_metadata_free_type (inflated); + klass->parent = mono_class_inflate_generic_class (gklass->parent, mono_generic_class_get_context (gclass)); } if (klass->parent) mono_class_setup_parent (klass, klass->parent); if (klass->enumtype) { - klass->enum_basetype = gklass->enum_basetype; klass->cast_class = gklass->cast_class; + klass->element_class = gklass->element_class; } if (gclass->is_dynamic) { @@ -4371,6 +4472,9 @@ mono_generic_class_get_class (MonoGenericClass *gclass) } mono_profiler_class_loaded (klass, MONO_PROFILE_OK); + + inflated_classes ++; + inflated_classes_size += sizeof (MonoClass); mono_loader_unlock (); @@ -4383,6 +4487,7 @@ mono_generic_class_get_class (MonoGenericClass *gclass) MonoClass * mono_class_from_generic_parameter (MonoGenericParam *param, MonoImage *image, gboolean is_mvar) { + MonoGenericContainer *container; MonoClass *klass, **ptr; int count, pos, i; @@ -4393,12 +4498,13 @@ mono_class_from_generic_parameter (MonoGenericParam *param, MonoImage *image, gb return param->pklass; } - if (!image && param->owner) { + container = mono_generic_param_owner (param); + if (!image && container) { if (is_mvar) { - MonoMethod *method = param->owner->owner.method; + MonoMethod *method = container->owner.method; image = (method && method->klass) ? method->klass->image : NULL; } else { - MonoClass *klass = param->owner->owner.klass; + MonoClass *klass = container->owner.klass; // FIXME: 'klass' should not be null // But, monodis creates GenericContainers without associating a owner to it image = klass ? klass->image : NULL; @@ -4410,11 +4516,14 @@ mono_class_from_generic_parameter (MonoGenericParam *param, MonoImage *image, gb klass = mono_image_alloc0 (image, sizeof (MonoClass)); + classes_size += sizeof (MonoClass); + if (param->name) klass->name = param->name; else { + int n = mono_generic_param_num (param); klass->name = mono_image_alloc0 (image, 16); - sprintf ((char*)klass->name, is_mvar ? "!!%d" : "!%d", param->num); + sprintf ((char*)klass->name, is_mvar ? "!!%d" : "!%d", n); } klass->name_space = ""; mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD); @@ -4445,28 +4554,27 @@ mono_class_from_generic_parameter (MonoGenericParam *param, MonoImage *image, gb klass->inited = TRUE; klass->cast_class = klass->element_class = klass; - klass->enum_basetype = &klass->element_class->byval_arg; klass->flags = TYPE_ATTRIBUTE_PUBLIC; klass->this_arg.type = klass->byval_arg.type = is_mvar ? MONO_TYPE_MVAR : MONO_TYPE_VAR; klass->this_arg.data.generic_param = klass->byval_arg.data.generic_param = param; klass->this_arg.byref = TRUE; - if (param->owner) { + if (container) { guint32 owner; guint32 cols [MONO_GENERICPARAM_SIZE]; MonoTableInfo *tdef = &image->tables [MONO_TABLE_GENERICPARAM]; i = 0; - if (is_mvar && param->owner->owner.method) - i = mono_metadata_get_generic_param_row (image, param->owner->owner.method->token, &owner); - else if (!is_mvar && param->owner->owner.klass) - i = mono_metadata_get_generic_param_row (image, param->owner->owner.klass->type_token, &owner); + if (is_mvar && container->owner.method) + i = mono_metadata_get_generic_param_row (image, container->owner.method->token, &owner); + else if (!is_mvar && container->owner.klass) + i = mono_metadata_get_generic_param_row (image, container->owner.klass->type_token, &owner); if (i) { mono_metadata_decode_row (tdef, i - 1, cols, MONO_GENERICPARAM_SIZE); do { - if (cols [MONO_GENERICPARAM_NUMBER] == param->num) { + if (cols [MONO_GENERICPARAM_NUMBER] == mono_generic_param_num (param)) { klass->sizes.generic_param_token = i | MONO_TOKEN_GENERIC_PARAM; break; } @@ -4512,6 +4620,8 @@ mono_ptr_class_get (MonoType *type) } result = mono_image_alloc0 (image, sizeof (MonoClass)); + classes_size += sizeof (MonoClass); + result->parent = NULL; /* no parent for PTR types */ result->name_space = el_class->name_space; name = g_strdup_printf ("%s*", el_class->name); @@ -4526,11 +4636,10 @@ mono_ptr_class_get (MonoType *type) /* Can pointers get boxed? */ result->instance_size = sizeof (gpointer); result->cast_class = result->element_class = el_class; - result->enum_basetype = &result->element_class->byval_arg; result->blittable = TRUE; result->this_arg.type = result->byval_arg.type = MONO_TYPE_PTR; - result->this_arg.data.type = result->byval_arg.data.type = result->enum_basetype; + result->this_arg.data.type = result->byval_arg.data.type = &result->element_class->byval_arg; result->this_arg.byref = TRUE; mono_class_setup_supertypes (result); @@ -4580,7 +4689,6 @@ mono_fnptr_class_get (MonoMethodSignature *sig) result->this_arg.type = result->byval_arg.type = MONO_TYPE_FNPTR; result->this_arg.data.method = result->byval_arg.data.method = sig; result->this_arg.byref = TRUE; - result->enum_basetype = &result->element_class->byval_arg; result->blittable = TRUE; mono_class_setup_supertypes (result); @@ -4729,17 +4837,34 @@ mono_bounded_array_class_get (MonoClass *eclass, guint32 rank, gboolean bounded) image = eclass->image; - mono_loader_lock (); + if (rank == 1 && !bounded) { + /* + * This case is very frequent not just during compilation because of calls + * from mono_class_from_mono_type (), mono_array_new (), + * Array:CreateInstance (), etc, so use a separate cache + a separate lock. + */ + EnterCriticalSection (&image->szarray_cache_lock); + if (!image->szarray_cache) + image->szarray_cache = g_hash_table_new (mono_aligned_addr_hash, NULL); + class = g_hash_table_lookup (image->szarray_cache, eclass); + LeaveCriticalSection (&image->szarray_cache_lock); + if (class) + return class; - if (!image->array_cache) - image->array_cache = g_hash_table_new (mono_aligned_addr_hash, NULL); + mono_loader_lock (); + } else { + mono_loader_lock (); - if ((rootlist = list = g_hash_table_lookup (image->array_cache, eclass))) { - for (; list; list = list->next) { - class = list->data; - if ((class->rank == rank) && (class->byval_arg.type == (((rank > 1) || bounded) ? MONO_TYPE_ARRAY : MONO_TYPE_SZARRAY))) { - mono_loader_unlock (); - return class; + if (!image->array_cache) + image->array_cache = g_hash_table_new (mono_aligned_addr_hash, NULL); + + if ((rootlist = list = g_hash_table_lookup (image->array_cache, eclass))) { + for (; list; list = list->next) { + class = list->data; + if ((class->rank == rank) && (class->byval_arg.type == (((rank > 1) || bounded) ? MONO_TYPE_ARRAY : MONO_TYPE_SZARRAY))) { + mono_loader_unlock (); + return class; + } } } } @@ -4773,6 +4898,8 @@ mono_bounded_array_class_get (MonoClass *eclass, guint32 rank, gboolean bounded) mono_profiler_class_event (class, MONO_PROFILE_START_LOAD); + classes_size += sizeof (MonoClass); + class->type_token = 0; /* all arrays are marked serializable and sealed, bug #42779 */ class->flags = TYPE_ATTRIBUTE_CLASS | TYPE_ATTRIBUTE_SERIALIZABLE | TYPE_ATTRIBUTE_SEALED | @@ -4780,7 +4907,7 @@ mono_bounded_array_class_get (MonoClass *eclass, guint32 rank, gboolean bounded) class->parent = parent; class->instance_size = mono_class_instance_size (class->parent); - if (eclass->enumtype && !eclass->enum_basetype) { + if (eclass->enumtype && !mono_class_enum_basetype (eclass)) { if (!eclass->reflection_info || eclass->wastypebuilder) { g_warning ("Only incomplete TypeBuilder objects are allowed to be an enum without base_type"); g_assert (eclass->reflection_info && !eclass->wastypebuilder); @@ -4792,18 +4919,6 @@ mono_bounded_array_class_get (MonoClass *eclass, guint32 rank, gboolean bounded) mono_class_setup_supertypes (class); - if (mono_defaults.generic_ilist_class && !bounded && rank == 1) { - MonoType *args [1]; - - /* generic IList, ICollection, IEnumerable */ - class->interface_count = 1; - class->interfaces = mono_image_alloc0 (image, sizeof (MonoClass*) * class->interface_count); - - args [0] = &eclass->byval_arg; - class->interfaces [0] = mono_class_bind_generic_parameters ( - mono_defaults.generic_ilist_class, 1, args, FALSE); - } - if (eclass->generic_class) mono_class_init (eclass); if (!eclass->size_inited) @@ -4838,8 +4953,21 @@ mono_bounded_array_class_get (MonoClass *eclass, guint32 rank, gboolean bounded) class->generic_container = eclass->generic_container; - list = g_slist_append (rootlist, class); - g_hash_table_insert (image->array_cache, eclass, list); + if (rank == 1 && !bounded) { + MonoClass *prev_class; + + EnterCriticalSection (&image->szarray_cache_lock); + prev_class = g_hash_table_lookup (image->szarray_cache, eclass); + if (prev_class) + /* Someone got in before us */ + class = prev_class; + else + g_hash_table_insert (image->szarray_cache, eclass, class); + LeaveCriticalSection (&image->szarray_cache_lock); + } else { + list = g_slist_append (rootlist, class); + g_hash_table_insert (image->array_cache, eclass, list); + } mono_loader_unlock (); @@ -5076,27 +5204,28 @@ mono_class_get_field_default_value (MonoClassField *field, MonoTypeEnum *def_typ g_assert (field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT); - if (!klass->field_def_values) { + if (!klass->ext || !klass->ext->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_class_alloc_ext (klass); + if (!klass->ext->field_def_values) + klass->ext->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) { + if (!klass->ext->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); - 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]); + klass->ext->field_def_values [field_index].def_type = constant_cols [MONO_CONSTANT_TYPE]; + klass->ext->field_def_values [field_index].data = (gpointer)mono_metadata_blob_heap (field->parent->image, constant_cols [MONO_CONSTANT_VALUE]); } - *def_type = klass->field_def_values [field_index].def_type; - return klass->field_def_values [field_index].data; + *def_type = klass->ext->field_def_values [field_index].def_type; + return klass->ext->field_def_values [field_index].data; } guint32 @@ -5106,9 +5235,11 @@ mono_class_get_event_token (MonoEvent *event) int i; while (klass) { - for (i = 0; i < klass->event.count; ++i) { - if (&klass->events [i] == event) - return mono_metadata_make_token (MONO_TABLE_EVENT, klass->event.first + i + 1); + if (klass->ext) { + for (i = 0; i < klass->ext->event.count; ++i) { + if (&klass->ext->events [i] == event) + return mono_metadata_make_token (MONO_TABLE_EVENT, klass->ext->event.first + i + 1); + } } klass = klass->parent; } @@ -5141,8 +5272,8 @@ mono_class_get_property_token (MonoProperty *prop) int i = 0; gpointer iter = NULL; while ((p = mono_class_get_properties (klass, &iter))) { - if (&klass->properties [i] == prop) - return mono_metadata_make_token (MONO_TABLE_PROPERTY, klass->property.first + i + 1); + if (&klass->ext->properties [i] == prop) + return mono_metadata_make_token (MONO_TABLE_PROPERTY, klass->ext->property.first + i + 1); i ++; } @@ -5756,7 +5887,7 @@ mono_class_has_variant_generic_params (MonoClass *klass) container = klass->generic_class->container_class->generic_container; for (i = 0; i < container->type_argc; ++i) - if (container->type_params [i].flags & (MONO_GEN_PARAM_VARIANT|MONO_GEN_PARAM_COVARIANT)) + if (mono_generic_container_get_param (container, i)->flags & (MONO_GEN_PARAM_VARIANT|MONO_GEN_PARAM_COVARIANT)) return TRUE; return FALSE; @@ -5834,9 +5965,9 @@ mono_class_is_assignable_from (MonoClass *klass, MonoClass *oklass) * _CONTRAVARIANT, but they are in a public header so we can't fix it. */ if (param1_class != param2_class) { - if ((container->type_params [i].flags & MONO_GEN_PARAM_VARIANT) && mono_class_is_assignable_from (param1_class, param2_class)) + if ((mono_generic_container_get_param (container, i)->flags & MONO_GEN_PARAM_VARIANT) && mono_class_is_assignable_from (param1_class, param2_class)) ; - else if (((container->type_params [i].flags & MONO_GEN_PARAM_COVARIANT) && mono_class_is_assignable_from (param2_class, param1_class))) + else if (((mono_generic_container_get_param (container, i)->flags & MONO_GEN_PARAM_COVARIANT) && mono_class_is_assignable_from (param2_class, param1_class))) ; else { match = FALSE; @@ -5997,7 +6128,7 @@ handle_enum: return 8; case MONO_TYPE_VALUETYPE: if (type->data.klass->enumtype) { - type = type->data.klass->enum_basetype; + type = mono_class_enum_basetype (type->data.klass); klass = klass->element_class; goto handle_enum; } @@ -6203,7 +6334,11 @@ mono_class_is_enum (MonoClass *klass) MonoType* mono_class_enum_basetype (MonoClass *klass) { - return klass->enum_basetype; + if (klass->element_class == klass) + /* SRE */ + return NULL; + else + return &klass->element_class->byval_arg; } /** @@ -6357,7 +6492,7 @@ mono_class_num_properties (MonoClass *klass) { mono_class_setup_properties (klass); - return klass->property.count; + return klass->ext->property.count; } /** @@ -6371,7 +6506,7 @@ mono_class_num_events (MonoClass *klass) { mono_class_setup_events (klass); - return klass->event.count; + return klass->ext->event.count; } /** @@ -6394,6 +6529,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]; @@ -6538,8 +6675,8 @@ mono_class_get_properties (MonoClass* klass, gpointer *iter) if (!*iter) { mono_class_setup_properties (klass); /* start from the first */ - if (klass->property.count) { - return *iter = &klass->properties [0]; + if (klass->ext->property.count) { + return *iter = &klass->ext->properties [0]; } else { /* no fields */ return NULL; @@ -6547,7 +6684,7 @@ mono_class_get_properties (MonoClass* klass, gpointer *iter) } property = *iter; property++; - if (property < &klass->properties [klass->property.count]) { + if (property < &klass->ext->properties [klass->ext->property.count]) { return *iter = property; } return NULL; @@ -6576,8 +6713,8 @@ mono_class_get_events (MonoClass* klass, gpointer *iter) if (!*iter) { mono_class_setup_events (klass); /* start from the first */ - if (klass->event.count) { - return *iter = &klass->events [0]; + if (klass->ext->event.count) { + return *iter = &klass->ext->events [0]; } else { /* no fields */ return NULL; @@ -6585,7 +6722,7 @@ mono_class_get_events (MonoClass* klass, gpointer *iter) } event = *iter; event++; - if (event < &klass->events [klass->event.count]) { + if (event < &klass->ext->events [klass->ext->event.count]) { return *iter = event; } return NULL; @@ -6609,9 +6746,11 @@ mono_class_get_interfaces (MonoClass* klass, gpointer *iter) MonoClass** iface; if (!iter) return NULL; - if (!klass->inited) - mono_class_init (klass); if (!*iter) { + if (!klass->inited) + mono_class_init (klass); + if (!klass->interfaces_inited) + mono_class_setup_interfaces (klass); /* start from the first */ if (klass->interface_count) { *iter = &klass->interfaces [0]; @@ -6664,7 +6803,8 @@ mono_class_get_nested_types (MonoClass* klass, gpointer *iter) guint32 cols [MONO_NESTED_CLASS_SIZE]; mono_metadata_decode_row (&klass->image->tables [MONO_TABLE_NESTEDCLASS], i - 1, cols, MONO_NESTED_CLASS_SIZE); nclass = mono_class_create_from_typedef (klass->image, MONO_TOKEN_TYPE_DEF | cols [MONO_NESTED_CLASS_NESTED]); - klass->nested_classes = g_list_prepend_mempool (klass->nested_classes, klass->image->mempool, nclass); + mono_class_alloc_ext (klass); + klass->ext->nested_classes = g_list_prepend_image (klass->image, klass->ext->nested_classes, nclass); i = mono_metadata_nesting_typedef (klass->image, klass->type_token, i + 1); } @@ -6676,9 +6816,9 @@ mono_class_get_nested_types (MonoClass* klass, gpointer *iter) if (!*iter) { /* start from the first */ - if (klass->nested_classes) { - *iter = klass->nested_classes; - return klass->nested_classes->data; + if (klass->ext && klass->ext->nested_classes) { + *iter = klass->ext->nested_classes; + return klass->ext->nested_classes->data; } else { /* no nested types */ return NULL; @@ -6765,23 +6905,24 @@ mono_field_get_rva (MonoClassField *field) g_assert (field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA); - if (!klass->field_def_values) { + if (!klass->ext || !klass->ext->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_class_alloc_ext (klass); + if (!klass->ext->field_def_values) + klass->ext->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) { + if (!klass->ext->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); + klass->ext->field_def_values [field_index].data = mono_image_rva_map (field->parent->image, rva); } - return klass->field_def_values [field_index].data; + return klass->ext->field_def_values [field_index].data; } /** @@ -7002,6 +7143,13 @@ mono_class_get_method_from_name_flags (MonoClass *klass, const char *name, int p mono_class_init (klass); + if (klass->generic_class && !klass->methods) { + res = mono_class_get_method_from_name_flags (klass->generic_class->container_class, name, param_count, flags); + if (res) + res = mono_class_inflate_generic_method_full (res, klass, mono_class_get_context (klass)); + return res; + } + if (klass->methods || !MONO_CLASS_HAS_STATIC_METADATA (klass)) { mono_class_setup_methods (klass); for (i = 0; i < klass->method.count; ++i) { @@ -7043,7 +7191,7 @@ mono_class_set_failure (MonoClass *klass, guint32 ex_type, void *ex_data) mono_loader_lock (); klass->exception_type = ex_type; if (ex_data) - mono_property_hash_insert (klass->image->property_hash, klass, MONO_CLASS_PROP_EXCEPTION_DATA, ex_data); + mono_image_property_insert (klass->image, klass, MONO_CLASS_PROP_EXCEPTION_DATA, ex_data); mono_loader_unlock (); return TRUE; @@ -7059,12 +7207,7 @@ mono_class_set_failure (MonoClass *klass, guint32 ex_type, void *ex_data) gpointer mono_class_get_exception_data (MonoClass *klass) { - gpointer res; - - mono_loader_lock (); - res = mono_property_hash_lookup (klass->image->property_hash, klass, MONO_CLASS_PROP_EXCEPTION_DATA); - mono_loader_unlock (); - return res; + return mono_image_property_lookup (klass->image, klass, MONO_CLASS_PROP_EXCEPTION_DATA); } /** @@ -7075,6 +7218,16 @@ mono_class_get_exception_data (MonoClass *klass) void mono_classes_init (void) { + mono_counters_register ("Inflated methods size", + MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_methods_size); + mono_counters_register ("Inflated classes", + MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_classes); + mono_counters_register ("Inflated classes size", + MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_classes_size); + mono_counters_register ("MonoClass size", + MONO_COUNTER_METADATA | MONO_COUNTER_INT, &classes_size); + mono_counters_register ("MonoClassExt size", + MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_ext_size); } /** @@ -7199,7 +7352,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; @@ -7653,3 +7806,85 @@ 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 (); +} + +/* + * mono_class_alloc_ext: + * + * Allocate klass->ext if not already done. + * LOCKING: Assumes the loader lock is held. + */ +void +mono_class_alloc_ext (MonoClass *klass) +{ + if (!klass->ext) { + if (klass->generic_class) { + klass->ext = g_new0 (MonoClassExt, 1); + } else { + klass->ext = mono_image_alloc0 (klass->image, sizeof (MonoClassExt)); + } + class_ext_size += sizeof (MonoClassExt); + } +} + +/* + * mono_class_setup_interfaces: + * + * Initialize class->interfaces/interfaces_count. + * LOCKING: Acquires the loader lock. + */ +void +mono_class_setup_interfaces (MonoClass *klass) +{ + int i; + + if (klass->interfaces_inited) + return; + + mono_loader_lock (); + + if (klass->interfaces_inited) { + mono_loader_unlock (); + return; + } + + if (klass->rank == 1 && klass->byval_arg.type != MONO_TYPE_ARRAY && mono_defaults.generic_ilist_class) { + MonoType *args [1]; + + /* generic IList, ICollection, IEnumerable */ + klass->interface_count = 1; + klass->interfaces = mono_image_alloc0 (klass->image, sizeof (MonoClass*) * klass->interface_count); + + args [0] = &klass->element_class->byval_arg; + klass->interfaces [0] = mono_class_bind_generic_parameters ( + mono_defaults.generic_ilist_class, 1, args, FALSE); + } else if (klass->generic_class) { + MonoClass *gklass = klass->generic_class->container_class; + + klass->interface_count = gklass->interface_count; + klass->interfaces = g_new0 (MonoClass *, klass->interface_count); + for (i = 0; i < klass->interface_count; i++) + klass->interfaces [i] = mono_class_inflate_generic_class (gklass->interfaces [i], mono_generic_class_get_context (klass->generic_class)); + } + + mono_memory_barrier (); + + klass->interfaces_inited = TRUE; + + mono_loader_unlock (); +}