X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mono%2Fmetadata%2Fclass.c;h=a6e7e437ce5a1454899cd25d907a000cb6a58505;hb=3eec2f72a9a3671567e63a743be887c5da1c8963;hp=7c3d3f7cbc20e3edb463a751dcbab54acf219972;hpb=54216914c34479b55bfb527181dc71d037000822;p=mono.git diff --git a/mono/metadata/class.c b/mono/metadata/class.c index 7c3d3f7cbc2..a6e7e437ce5 100644 --- a/mono/metadata/class.c +++ b/mono/metadata/class.c @@ -15,7 +15,6 @@ #include #include #include -#include #if !PLATFORM_WIN32 #include #endif @@ -298,9 +297,11 @@ mono_type_get_name_recurse (MonoType *type, GString *str, gboolean is_recursed, } case MONO_TYPE_VAR: case MONO_TYPE_MVAR: - g_assert (type->data.generic_param->name); - g_string_append (str, type->data.generic_param->name); - + if (!mono_generic_param_info (type->data.generic_param)) + g_string_append_printf (str, "%s%d", type->type == MONO_TYPE_VAR ? "!" : "!!", type->data.generic_param->num); + else + g_string_append (str, mono_generic_param_info (type->data.generic_param)->name); + mono_type_name_check_byref (type, str); break; @@ -368,7 +369,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, mono_generic_container_get_param (klass->generic_container, i)->name); + g_string_append (str, mono_generic_container_get_param_info (klass->generic_container, i)->name); } if (format == MONO_TYPE_NAME_FORMAT_IL) g_string_append_c (str, '>'); @@ -497,7 +498,8 @@ inflate_generic_type (MonoImage *image, MonoType *type, MonoGenericContext *cont if (!inst || !inst->type_argv) return NULL; if (num >= inst->type_argc) - g_error ("MVAR %d (%s) cannot be expanded in this context with %d instantiations", num, type->data.generic_param->name, inst->type_argc); + g_error ("MVAR %d (%s) cannot be expanded in this context with %d instantiations", + num, mono_generic_param_info (type->data.generic_param)->name, inst->type_argc); /* * Note that the VAR/MVAR cases are different from the rest. The other cases duplicate @type, @@ -516,7 +518,8 @@ inflate_generic_type (MonoImage *image, MonoType *type, MonoGenericContext *cont 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); + g_error ("VAR %d (%s) cannot be expanded in this context with %d instantiations", + num, mono_generic_param_info (type->data.generic_param)->name, inst->type_argc); nt = mono_metadata_type_dup (image, inst->type_argv [num]); nt->byref = type->byref; nt->attrs = type->attrs; @@ -1071,6 +1074,7 @@ mono_class_setup_fields (MonoClass *class) MonoClass *gklass = class->generic_class->container_class; mono_class_setup_fields (gklass); top = gklass->field.count; + class->field.first = gklass->field.first; class->field.count = gklass->field.count; } @@ -1778,12 +1782,6 @@ mono_class_get_vtable_entry (MonoClass *class, int offset) 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; } @@ -4481,75 +4479,52 @@ 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) +static MonoClass* +make_generic_param_class (MonoGenericParam *param, MonoImage *image, gboolean is_mvar, MonoGenericParamInfo *pinfo) { - MonoGenericContainer *container; MonoClass *klass, **ptr; int count, pos, i; - mono_loader_lock (); - - if (param->pklass) { - mono_loader_unlock (); - return param->pklass; - } - - container = mono_generic_param_owner (param); - if (!image && container) { - if (is_mvar) { - MonoMethod *method = container->owner.method; - image = (method && method->klass) ? method->klass->image : NULL; - } else { - 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; - } - } if (!image) /* FIXME: */ image = mono_defaults.corlib; klass = mono_image_alloc0 (image, sizeof (MonoClass)); - classes_size += sizeof (MonoClass); - if (param->name) - klass->name = param->name; - else { + if (pinfo) { + klass->name = pinfo->name; + } else { int n = mono_generic_param_num (param); klass->name = mono_image_alloc0 (image, 16); - sprintf ((char*)klass->name, is_mvar ? "!!%d" : "!%d", n); + sprintf ((char*)klass->name, "%d", n); } + klass->name_space = ""; mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD); - - for (count = 0, ptr = param->constraints; ptr && *ptr; ptr++, count++) - ; + + count = 0; + if (pinfo) + for (ptr = pinfo->constraints; ptr && *ptr; ptr++, count++) + ; pos = 0; - if ((count > 0) && !MONO_CLASS_IS_INTERFACE (param->constraints [0])) { - klass->parent = param->constraints [0]; + if ((count > 0) && !MONO_CLASS_IS_INTERFACE (pinfo->constraints [0])) { + klass->parent = pinfo->constraints [0]; pos++; - } else if (param->flags & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT) + } else if (pinfo && pinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT) klass->parent = mono_class_from_name (mono_defaults.corlib, "System", "ValueType"); else klass->parent = mono_defaults.object_class; + if (count - pos > 0) { klass->interface_count = count - pos; klass->interfaces = mono_image_alloc0 (image, sizeof (MonoClass *) * (count - pos)); for (i = pos; i < count; i++) - klass->interfaces [i - pos] = param->constraints [i]; + klass->interfaces [i - pos] = pinfo->constraints [i]; } - if (!image) - image = mono_defaults.corlib; - klass->image = image; klass->inited = TRUE; @@ -4560,39 +4535,107 @@ mono_class_from_generic_parameter (MonoGenericParam *param, MonoImage *image, gb klass->this_arg.data.generic_param = klass->byval_arg.data.generic_param = param; klass->this_arg.byref = TRUE; + /* FIXME: shouldn't this be ->type_token? */ + klass->sizes.generic_param_token = pinfo ? pinfo->token : 0; + + mono_class_setup_supertypes (klass); + + return klass; +} + +#define FAST_CACHE_SIZE 1024 +static MonoClass *var_cache_fast [FAST_CACHE_SIZE]; +static MonoClass *mvar_cache_fast [FAST_CACHE_SIZE]; +static GHashTable *var_cache_slow; +static GHashTable *mvar_cache_slow; + +static MonoClass * +get_anon_gparam_class (MonoGenericParam *param, gboolean is_mvar) +{ + int n = mono_generic_param_num (param); + GHashTable *ht; + + if (n < FAST_CACHE_SIZE) + return (is_mvar ? mvar_cache_fast : var_cache_fast) [n]; + ht = is_mvar ? mvar_cache_slow : var_cache_slow; + return ht ? g_hash_table_lookup (ht, GINT_TO_POINTER (n)) : NULL; +} + +static void +set_anon_gparam_class (MonoGenericParam *param, gboolean is_mvar, MonoClass *klass) +{ + int n = mono_generic_param_num (param); + GHashTable *ht; + + if (n < FAST_CACHE_SIZE) { + (is_mvar ? mvar_cache_fast : var_cache_fast) [n] = klass; + return; + } + ht = is_mvar ? mvar_cache_slow : var_cache_slow; + if (!ht) { + ht = g_hash_table_new (NULL, NULL); + if (is_mvar) + mvar_cache_slow = ht; + else + var_cache_slow = ht; + } + + g_hash_table_insert (ht, GINT_TO_POINTER (n), klass); +} + +/* + * LOCKING: Acquires the loader lock. + */ +MonoClass * +mono_class_from_generic_parameter (MonoGenericParam *param, MonoImage *image, gboolean is_mvar) +{ + MonoGenericContainer *container = mono_generic_param_owner (param); + MonoGenericParamInfo *pinfo; + MonoClass *klass; + + mono_loader_lock (); + if (container) { - guint32 owner; - guint32 cols [MONO_GENERICPARAM_SIZE]; - MonoTableInfo *tdef = &image->tables [MONO_TABLE_GENERICPARAM]; - i = 0; - - 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] == mono_generic_param_num (param)) { - klass->sizes.generic_param_token = i | MONO_TOKEN_GENERIC_PARAM; - break; - } - if (++i > tdef->rows) - break; - mono_metadata_decode_row (tdef, i - 1, cols, MONO_GENERICPARAM_SIZE); - } while (cols [MONO_GENERICPARAM_OWNER] == owner); + pinfo = mono_generic_param_info (param); + if (pinfo->pklass) { + mono_loader_unlock (); + return pinfo->pklass; + } + } else { + pinfo = NULL; + image = NULL; + + klass = get_anon_gparam_class (param, is_mvar); + if (klass) { + mono_loader_unlock (); + return klass; } } - mono_class_setup_supertypes (klass); + if (!image && container) { + if (is_mvar) { + MonoMethod *method = container->owner.method; + image = (method && method->klass) ? method->klass->image : NULL; + } else { + 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; + } + } + + klass = make_generic_param_class (param, image, is_mvar, pinfo); mono_memory_barrier (); - param->pklass = klass; + if (container) + pinfo->pklass = klass; + else + set_anon_gparam_class (param, is_mvar, klass); mono_loader_unlock (); + /* FIXME: Should this go inside 'make_generic_param_klass'? */ mono_profiler_class_loaded (klass, MONO_PROFILE_OK); return klass; @@ -5887,7 +5930,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 (mono_generic_container_get_param (container, i)->flags & (MONO_GEN_PARAM_VARIANT|MONO_GEN_PARAM_COVARIANT)) + if (mono_generic_container_get_param_info (container, i)->flags & (MONO_GEN_PARAM_VARIANT|MONO_GEN_PARAM_COVARIANT)) return TRUE; return FALSE; @@ -5965,9 +6008,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 ((mono_generic_container_get_param (container, i)->flags & MONO_GEN_PARAM_VARIANT) && mono_class_is_assignable_from (param1_class, param2_class)) + if ((mono_generic_container_get_param_info (container, i)->flags & MONO_GEN_PARAM_VARIANT) && mono_class_is_assignable_from (param1_class, param2_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 if (((mono_generic_container_get_param_info (container, i)->flags & MONO_GEN_PARAM_COVARIANT) && mono_class_is_assignable_from (param2_class, param1_class))) ; else { match = FALSE; @@ -7469,7 +7512,15 @@ can_access_instantiation (MonoClass *access_klass, MonoGenericInst *ginst) static gboolean can_access_type (MonoClass *access_klass, MonoClass *member_klass) { - int access_level = member_klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK; + int access_level; + + if (access_klass->element_class && !access_klass->enumtype) + access_klass = access_klass->element_class; + + if (member_klass->element_class && !member_klass->enumtype) + member_klass = member_klass->element_class; + + access_level = member_klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK; if (member_klass->byval_arg.type == MONO_TYPE_VAR || member_klass->byval_arg.type == MONO_TYPE_MVAR) return TRUE; @@ -7758,6 +7809,14 @@ mono_generic_class_is_generic_type_definition (MonoGenericClass *gklass) return gklass->context.class_inst == gklass->container_class->generic_container->context.class_inst; } +static gboolean gshared_supported; + +void +mono_set_generic_sharing_supported (gboolean supported) +{ + gshared_supported = supported; +} + /* * mono_class_generic_sharing_enabled: * @class: a class @@ -7771,19 +7830,13 @@ 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(__mono_ppc__) - static gboolean supported = TRUE; -#else - /* Not supported by the JIT backends */ - static gboolean supported = FALSE; -#endif static int generic_sharing = MONO_GENERIC_SHARING_NONE; static gboolean inited = FALSE; if (!inited) { const char *option; - if (supported) + if (gshared_supported) generic_sharing = MONO_GENERIC_SHARING_ALL; else generic_sharing = MONO_GENERIC_SHARING_NONE; @@ -7801,7 +7854,7 @@ mono_class_generic_sharing_enabled (MonoClass *class) g_warning ("Unknown generic sharing option `%s'.", option); } - if (!supported) + if (!gshared_supported) generic_sharing = MONO_GENERIC_SHARING_NONE; inited = TRUE;