#include <stdio.h>
#include <string.h>
#include <stdlib.h>
-#include <signal.h>
#if !PLATFORM_WIN32
#include <mono/io-layer/atomic.h>
#endif
}
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;
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, '>');
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,
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;
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;
}
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;
}
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;
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;
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;
* _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;
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;
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
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;
g_warning ("Unknown generic sharing option `%s'.", option);
}
- if (!supported)
+ if (!gshared_supported)
generic_sharing = MONO_GENERIC_SHARING_NONE;
inited = TRUE;