MonoClass *parent = class->parent;
MonoClass *subclass;
MonoRuntimeGenericContextTemplate *rgctx_template = class_lookup_rgctx_template (class);
- static gboolean hook_installed;
-
- if (!hook_installed) {
- mono_install_image_unload_hook (mono_class_unregister_image_generic_subclasses, NULL);
- hook_installed = TRUE;
- }
g_assert (rgctx_template);
#define MONO_RGCTX_SLOT_USED_MARKER ((gpointer)&mono_defaults.object_class->byval_arg)
+/*
+ * Return true if this info type has the notion of identify.
+ *
+ * Some info types expect that each insert results in a new slot been assigned.
+ */
+static int
+other_info_has_identity (int info_type)
+{
+ return info_type != MONO_RGCTX_INFO_CAST_CACHE;
+}
+
/*
* LOCKING: loader lock
*/
case MONO_RGCTX_INFO_KLASS:
case MONO_RGCTX_INFO_VTABLE:
case MONO_RGCTX_INFO_TYPE:
- case MONO_RGCTX_INFO_REFLECTION_TYPE: {
+ case MONO_RGCTX_INFO_REFLECTION_TYPE:
+ case MONO_RGCTX_INFO_CAST_CACHE: {
gpointer result = mono_class_inflate_generic_type_with_mempool (temporary ? NULL : class->image,
data, context, &error);
g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
case MONO_RGCTX_INFO_VTABLE:
case MONO_RGCTX_INFO_TYPE:
case MONO_RGCTX_INFO_REFLECTION_TYPE:
+ case MONO_RGCTX_INFO_CAST_CACHE:
mono_metadata_free_type (info);
break;
default:
return class;
}
+static gboolean
+generic_inst_is_sharable (MonoGenericInst *inst, gboolean allow_type_vars,
+ gboolean allow_partial)
+{
+ int i;
+
+ for (i = 0; i < inst->type_argc; ++i) {
+ MonoType *type = inst->type_argv [i];
+
+ if (MONO_TYPE_IS_REFERENCE (type) || (allow_type_vars && (type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR)))
+ continue;
+
+ /*
+ * Allow non ref arguments, if there is at least one ref argument
+ * (partial sharing).
+ * FIXME: Allow more types
+ */
+ if (allow_partial && !type->byref && (((type->type >= MONO_TYPE_BOOLEAN) && (type->type <= MONO_TYPE_R8)) || (type->type == MONO_TYPE_I) || (type->type == MONO_TYPE_U)))
+ continue;
+
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
/*
* mono_is_partially_sharable_inst:
*
g_free (type_argv);
return mono_class_inflate_generic_class (class->generic_class->container_class, &shared_context);
+ } else if (!generic_inst_is_sharable (inst, TRUE, FALSE)) {
+ /* Happens for partially shared methods of nono-sharable generic class */
+ return class;
}
}
if (template)
return template;
- g_assert (get_shared_class (class) == class);
+ //g_assert (get_shared_class (class) == class);
template = alloc_template (class);
mono_raise_exception (mono_class_get_exception_for_failure (class));
return vtable;
}
+ case MONO_RGCTX_INFO_CAST_CACHE: {
+ /*First slot is the cache itself, the second the vtable.*/
+ gpointer **cache_data = mono_domain_alloc0 (domain, sizeof (gpointer) * 2);
+ cache_data [1] = (gpointer)class;
+ return cache_data;
+ }
default:
g_assert_not_reached ();
}
case MONO_RGCTX_INFO_STATIC_DATA:
case MONO_RGCTX_INFO_KLASS:
case MONO_RGCTX_INFO_VTABLE:
+ case MONO_RGCTX_INFO_CAST_CACHE:
temporary = TRUE;
break;
default:
switch (oti->info_type) {
case MONO_RGCTX_INFO_STATIC_DATA:
case MONO_RGCTX_INFO_KLASS:
- case MONO_RGCTX_INFO_VTABLE: {
+ case MONO_RGCTX_INFO_VTABLE:
+ case MONO_RGCTX_INFO_CAST_CACHE: {
MonoClass *arg_class = mono_class_from_mono_type (data);
free_inflated_info (oti->info_type, data);
MonoRuntimeGenericContextOtherInfoTemplate subclass_oti;
MonoRuntimeGenericContextTemplate *subclass_template = class_lookup_rgctx_template (subclass);
- g_assert (!subclass->generic_class);
g_assert (subclass_template);
subclass_oti = class_get_rgctx_template_oti (subclass->parent, type_argc, index, FALSE, FALSE, NULL);
case MONO_RGCTX_INFO_VTABLE:
case MONO_RGCTX_INFO_TYPE:
case MONO_RGCTX_INFO_REFLECTION_TYPE:
+ case MONO_RGCTX_INFO_CAST_CACHE:
return mono_class_from_mono_type (data1) == mono_class_from_mono_type (data2);
case MONO_RGCTX_INFO_METHOD:
case MONO_RGCTX_INFO_GENERIC_METHOD_CODE:
mono_loader_lock ();
- oti_list = get_other_info_templates (rgctx_template, type_argc);
+ if (other_info_has_identity (info_type)) {
+ oti_list = get_other_info_templates (rgctx_template, type_argc);
- for (oti = oti_list, i = 0; oti; oti = oti->next, ++i) {
- gpointer inflated_data;
+ for (oti = oti_list, i = 0; oti; oti = oti->next, ++i) {
+ gpointer inflated_data;
- if (oti->info_type != info_type || !oti->data)
- continue;
+ if (oti->info_type != info_type || !oti->data)
+ continue;
- inflated_data = inflate_other_info (oti, generic_context, class, TRUE);
+ inflated_data = inflate_other_info (oti, generic_context, class, TRUE);
- if (other_info_equal (data, inflated_data, info_type)) {
+ if (other_info_equal (data, inflated_data, info_type)) {
+ free_inflated_info (info_type, inflated_data);
+ mono_loader_unlock ();
+ return i;
+ }
free_inflated_info (info_type, inflated_data);
- mono_loader_unlock ();
- return i;
}
- free_inflated_info (info_type, inflated_data);
}
/* We haven't found the info */
return mrgctx;
}
-static gboolean
-generic_inst_is_sharable (MonoGenericInst *inst, gboolean allow_type_vars,
- gboolean allow_partial)
-{
- gboolean has_refs;
- int i;
-
- has_refs = FALSE;
- for (i = 0; i < inst->type_argc; ++i) {
- MonoType *type = inst->type_argv [i];
-
- if (MONO_TYPE_IS_REFERENCE (type) || (allow_type_vars && (type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR)))
- has_refs = TRUE;
- }
-
- for (i = 0; i < inst->type_argc; ++i) {
- MonoType *type = inst->type_argv [i];
-
- if (MONO_TYPE_IS_REFERENCE (type) || (allow_type_vars && (type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR)))
- continue;
-
- /*
- * Allow non ref arguments, if there is at least one ref argument
- * (partial sharing).
- * FIXME: Allow more types
- */
- if (!type->byref && type->type == MONO_TYPE_I4 && has_refs && allow_partial)
- continue;
-
- return FALSE;
- }
-
- return TRUE;
-}
-
/*
* mono_generic_context_is_sharable_full:
* @context: a generic context
void
mono_generic_sharing_init (void)
{
+ mono_install_image_unload_hook (mono_class_unregister_image_generic_subclasses, NULL);
+}
+
+void
+mono_generic_sharing_cleanup (void)
+{
+ mono_remove_image_unload_hook (mono_class_unregister_image_generic_subclasses, NULL);
+
+ if (generic_subclass_hash)
+ g_hash_table_destroy (generic_subclass_hash);
+}
+
+gboolean
+mini_type_is_reference (MonoCompile *cfg, MonoType *type)
+{
+ if (mono_type_is_reference (type))
+ return TRUE;
+ if (!cfg->generic_sharing_context)
+ return FALSE;
+ /*FIXME the probably needs better handle under partial sharing*/
+ return type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR;
}