static void
mono_class_unregister_image_generic_subclasses (MonoImage *image, gpointer user_data);
-static gboolean partial_supported = FALSE;
+/* Counters */
+static int num_templates_allocted;
+static int num_templates_bytes;
+static int num_oti_allocted;
+static int num_oti_bytes;
+
+static gboolean partial_supported = TRUE;
static inline gboolean
partial_sharing_supported (void)
static MonoRuntimeGenericContextTemplate*
alloc_template (MonoClass *klass)
{
- static gboolean inited = FALSE;
- static int num_allocted = 0;
- static int num_bytes = 0;
-
int size = sizeof (MonoRuntimeGenericContextTemplate);
- if (!inited) {
- mono_counters_register ("RGCTX template num allocted", MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &num_allocted);
- mono_counters_register ("RGCTX template bytes allocted", MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &num_bytes);
- inited = TRUE;
- }
-
- num_allocted++;
- num_bytes += size;
+ num_templates_allocted++;
+ num_templates_bytes += size;
return mono_image_alloc0 (klass->image, size);
}
+/* LOCKING: Takes the loader lock */
static MonoRuntimeGenericContextInfoTemplate*
alloc_oti (MonoImage *image)
{
- static gboolean inited = FALSE;
- static int num_allocted = 0;
- static int num_bytes = 0;
-
int size = sizeof (MonoRuntimeGenericContextInfoTemplate);
- if (!inited) {
- mono_counters_register ("RGCTX oti num allocted", MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &num_allocted);
- mono_counters_register ("RGCTX oti bytes allocted", MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &num_bytes);
- inited = TRUE;
- }
-
- num_allocted++;
- num_bytes += size;
+ num_oti_allocted++;
+ num_oti_bytes += size;
return mono_image_alloc0 (image, size);
}
return GUINT_TO_POINTER (mono_class_value_size (klass, NULL));
case MONO_RGCTX_INFO_CLASS_BOX_TYPE:
if (MONO_TYPE_IS_REFERENCE (&klass->byval_arg))
- return GUINT_TO_POINTER (1);
+ return GUINT_TO_POINTER (MONO_GSHAREDVT_BOX_TYPE_REF);
else if (mono_class_is_nullable (klass))
- return GUINT_TO_POINTER (2);
+ return GUINT_TO_POINTER (MONO_GSHAREDVT_BOX_TYPE_NULLABLE);
else
- return GUINT_TO_POINTER (0);
+ return GUINT_TO_POINTER (MONO_GSHAREDVT_BOX_TYPE_VTYPE);
case MONO_RGCTX_INFO_MEMCPY:
case MONO_RGCTX_INFO_BZERO: {
static MonoMethod *memcpy_method [17];
MonoJumpInfoVirtMethod *info = data;
MonoClass *iface_class = info->method->klass;
MonoMethod *method;
+ MonoError error;
int ioffset, slot;
gpointer addr;
g_assert (info->klass->vtable);
method = info->klass->vtable [ioffset + slot];
+ method = mono_class_inflate_generic_method_checked (method, context, &error);
+
addr = mono_compile_method (method);
return mini_add_method_trampoline (method, addr, mono_method_needs_static_rgctx_invoke (method, FALSE), FALSE);
}
impl_class = method->klass;
if (MONO_TYPE_IS_REFERENCE (&impl_class->byval_arg))
- return GUINT_TO_POINTER (1);
+ return GUINT_TO_POINTER (MONO_GSHAREDVT_BOX_TYPE_REF);
else if (mono_class_is_nullable (impl_class))
- return GUINT_TO_POINTER (2);
+ return GUINT_TO_POINTER (MONO_GSHAREDVT_BOX_TYPE_NULLABLE);
else
- return GUINT_TO_POINTER (0);
+ return GUINT_TO_POINTER (MONO_GSHAREDVT_BOX_TYPE_VTYPE);
}
#ifndef DISABLE_REMOTING
case MONO_RGCTX_INFO_REMOTING_INVOKE_WITH_CHECK:
case MONO_RGCTX_INFO_FIELD_OFFSET: {
MonoClassField *field = data;
+ /* The value is offset by 1 */
if (field->parent->valuetype && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC))
- return GUINT_TO_POINTER (field->offset - sizeof (MonoObject));
+ return GUINT_TO_POINTER (field->offset - sizeof (MonoObject) + 1);
else
- return GUINT_TO_POINTER (field->offset);
+ return GUINT_TO_POINTER (field->offset + 1);
}
case MONO_RGCTX_INFO_METHOD_RGCTX: {
MonoMethodInflated *method = data;
method_inst ? method_inst->type_argc : 0, slot, TRUE, TRUE, &do_free);
/* This might take the loader lock */
info = instantiate_info (domain, &oti, &context, klass);
+ g_assert (info);
/*
if (method_inst)
void
mono_generic_sharing_init (void)
{
+ mono_counters_register ("RGCTX template num allocted", MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &num_templates_allocted);
+ mono_counters_register ("RGCTX template bytes allocted", MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &num_templates_bytes);
+ mono_counters_register ("RGCTX oti num allocted", MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &num_oti_allocted);
+ mono_counters_register ("RGCTX oti bytes allocted", MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &num_oti_bytes);
+
mono_install_image_unload_hook (mono_class_unregister_image_generic_subclasses, NULL);
}
}
}
-typedef struct {
- MonoGenericParam *par;
- MonoType *constraint;
-} SharedGParam;
-
static guint
shared_gparam_hash (gconstpointer data)
{
- SharedGParam *p = (SharedGParam*)data;
+ MonoGSharedGenericParam *p = (MonoGSharedGenericParam*)data;
guint hash;
- hash = mono_metadata_generic_param_hash (p->par);
- hash = ((hash << 5) - hash) ^ mono_metadata_type_hash (p->constraint);
+ hash = mono_metadata_generic_param_hash (p->parent);
+ hash = ((hash << 5) - hash) ^ mono_metadata_type_hash (p->param.param.gshared_constraint);
return hash;
}
static gboolean
shared_gparam_equal (gconstpointer ka, gconstpointer kb)
{
- SharedGParam *p1 = (SharedGParam*)ka;
- SharedGParam *p2 = (SharedGParam*)kb;
+ MonoGSharedGenericParam *p1 = (MonoGSharedGenericParam*)ka;
+ MonoGSharedGenericParam *p2 = (MonoGSharedGenericParam*)kb;
if (p1 == p2)
return TRUE;
- if (p1->par != p2->par)
+ if (p1->parent != p2->parent)
return FALSE;
- if (!mono_metadata_type_equal (p1->constraint, p2->constraint))
+ if (!mono_metadata_type_equal (p1->param.param.gshared_constraint, p2->param.param.gshared_constraint))
return FALSE;
return TRUE;
}
/*
- * get_shared_gparam:
+ * mini_get_shared_gparam:
*
- * Create an anonymous gparam with a type variable with a constraint which encodes which types can match it.
+ * Create an anonymous gparam from T with a constraint which encodes which types can match it.
*/
-static MonoType*
-get_shared_gparam (MonoType *t, MonoType *constraint)
+MonoType*
+mini_get_shared_gparam (MonoType *t, MonoType *constraint)
{
MonoGenericParam *par = t->data.generic_param;
- MonoGenericParam *copy;
- SharedGParam key;
+ MonoGSharedGenericParam *copy, key;
MonoType *res;
MonoImage *image = NULL;
char *name;
memset (&key, 0, sizeof (key));
- key.par = par;
- key.constraint = constraint;
+ key.parent = par;
+ key.param.param.gshared_constraint = constraint;
g_assert (mono_generic_param_info (par));
- /* image might not be set for sre */
- if (par->owner && par->owner->image) {
- image = par->owner->image;
+ image = get_image_for_generic_param(par);
- mono_image_lock (image);
- if (!image->gshared_types) {
- image->gshared_types_len = MONO_TYPE_INTERNAL;
- image->gshared_types = g_new0 (GHashTable*, image->gshared_types_len);
- }
- if (!image->gshared_types [constraint->type])
- image->gshared_types [constraint->type] = g_hash_table_new (shared_gparam_hash, shared_gparam_equal);
- res = g_hash_table_lookup (image->gshared_types [constraint->type], &key);
- mono_image_unlock (image);
- if (res)
- return res;
- copy = mono_image_alloc0 (image, sizeof (MonoGenericParamFull));
- memcpy (copy, par, sizeof (MonoGenericParamFull));
- name = get_shared_gparam_name (constraint->type, ((MonoGenericParamFull*)copy)->info.name);
- ((MonoGenericParamFull*)copy)->info.name = mono_image_strdup (image, name);
- g_free (name);
- } else {
- /* mono_generic_param_name () expects this to be a MonoGenericParamFull */
- copy = (MonoGenericParam*)g_new0 (MonoGenericParamFull, 1);
- memcpy (copy, par, sizeof (MonoGenericParam));
- }
- copy->owner = NULL;
- // FIXME:
- copy->image = image ? image : mono_defaults.corlib;
+ /*
+ * Need a cache to ensure the newly created gparam
+ * is unique wrt T/CONSTRAINT.
+ */
+ mono_image_lock (image);
+ if (!image->gshared_types) {
+ image->gshared_types_len = MONO_TYPE_INTERNAL;
+ image->gshared_types = g_new0 (GHashTable*, image->gshared_types_len);
+ }
+ if (!image->gshared_types [constraint->type])
+ image->gshared_types [constraint->type] = g_hash_table_new (shared_gparam_hash, shared_gparam_equal);
+ res = g_hash_table_lookup (image->gshared_types [constraint->type], &key);
+ mono_image_unlock (image);
+ if (res)
+ return res;
+ copy = mono_image_alloc0 (image, sizeof (MonoGSharedGenericParam));
+ memcpy (©->param, par, sizeof (MonoGenericParamFull));
+ name = get_shared_gparam_name (constraint->type, ((MonoGenericParamFull*)copy)->info.name);
+ copy->param.info.name = mono_image_strdup (image, name);
+ g_free (name);
+
+ copy->param.param.owner = par->owner;
- copy->gshared_constraint = constraint;
+ copy->param.param.gshared_constraint = constraint;
+ copy->parent = par;
res = mono_metadata_type_dup (NULL, t);
- res->data.generic_param = copy;
+ res->data.generic_param = (MonoGenericParam*)copy;
if (image) {
- SharedGParam *dkey;
-
- dkey = mono_image_alloc0 (image, sizeof (SharedGParam));
- dkey->par = par;
- dkey->constraint = constraint;
-
mono_image_lock (image);
/* Duplicates are ok */
- g_hash_table_insert (image->gshared_types [constraint->type], dkey, res);
+ g_hash_table_insert (image->gshared_types [constraint->type], copy, res);
mono_image_unlock (image);
}
k = mono_class_inflate_generic_class (gclass->container_class, &context);
- return get_shared_gparam (t, &k->byval_arg);
+ return mini_get_shared_gparam (t, &k->byval_arg);
} else if (MONO_TYPE_ISSTRUCT (type)) {
return type;
}
ttype = MONO_TYPE_OBJECT;
} else if (type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR) {
if (type->data.generic_param->gshared_constraint)
- return get_shared_gparam (t, type->data.generic_param->gshared_constraint);
+ return mini_get_shared_gparam (t, type->data.generic_param->gshared_constraint);
ttype = MONO_TYPE_OBJECT;
}
t2.type = ttype;
klass = mono_class_from_mono_type (&t2);
- return get_shared_gparam (t, &klass->byval_arg);
+ return mini_get_shared_gparam (t, &klass->byval_arg);
}
}
get_gsharedvt_type (MonoType *t)
{
/* Use TypeHandle as the constraint type since its a valuetype */
- return get_shared_gparam (t, &mono_defaults.typehandle_class->byval_arg);
+ return mini_get_shared_gparam (t, &mono_defaults.typehandle_class->byval_arg);
}
static MonoGenericInst*