* Author:
* Mark Probst (mark.probst@gmail.com)
*
- * (C) 2007 Novell, Inc.
+ * Copyright 2007-2011 Novell, Inc (http://www.novell.com)
+ * Copyright 2011 Xamarin, Inc (http://www.xamarin.com)
*/
#include <config.h>
//#define ALLOW_PARTIAL_SHARING TRUE
#define ALLOW_PARTIAL_SHARING FALSE
+
+#if 0
+#define DEBUG(...) __VA_ARGS__
+#else
+#define DEBUG(...)
+#endif
static void
mono_class_unregister_image_generic_subclasses (MonoImage *image, gpointer user_data);
/*
* LOCKING: loader lock
*/
-static MonoRuntimeGenericContextOtherInfoTemplate*
-get_other_info_templates (MonoRuntimeGenericContextTemplate *template, int type_argc)
+static MonoRuntimeGenericContextInfoTemplate*
+get_info_templates (MonoRuntimeGenericContextTemplate *template, int type_argc)
{
g_assert (type_argc >= 0);
if (type_argc == 0)
- return template->other_infos;
+ return template->infos;
return g_slist_nth_data (template->method_templates, type_argc - 1);
}
* LOCKING: loader lock
*/
static void
-set_other_info_templates (MonoImage *image, MonoRuntimeGenericContextTemplate *template, int type_argc,
- MonoRuntimeGenericContextOtherInfoTemplate *oti)
+set_info_templates (MonoImage *image, MonoRuntimeGenericContextTemplate *template, int type_argc,
+ MonoRuntimeGenericContextInfoTemplate *oti)
{
g_assert (type_argc >= 0);
if (type_argc == 0)
- template->other_infos = oti;
+ template->infos = oti;
else {
int length = g_slist_length (template->method_templates);
GSList *list;
/*
* LOCKING: loader lock
*/
-static MonoRuntimeGenericContextOtherInfoTemplate*
+static MonoRuntimeGenericContextInfoTemplate*
rgctx_template_get_other_slot (MonoRuntimeGenericContextTemplate *template, int type_argc, int slot)
{
int i;
- MonoRuntimeGenericContextOtherInfoTemplate *oti;
+ MonoRuntimeGenericContextInfoTemplate *oti;
g_assert (slot >= 0);
- for (oti = get_other_info_templates (template, type_argc), i = 0; i < slot; oti = oti->next, ++i) {
+ for (oti = get_info_templates (template, type_argc), i = 0; i < slot; oti = oti->next, ++i) {
if (!oti)
return NULL;
}
* LOCKING: loader lock
*/
static int
-rgctx_template_num_other_infos (MonoRuntimeGenericContextTemplate *template, int type_argc)
+rgctx_template_num_infos (MonoRuntimeGenericContextTemplate *template, int type_argc)
{
- MonoRuntimeGenericContextOtherInfoTemplate *oti;
+ MonoRuntimeGenericContextInfoTemplate *oti;
int i;
- for (i = 0, oti = get_other_info_templates (template, type_argc); oti; ++i, oti = oti->next)
+ for (i = 0, oti = get_info_templates (template, type_argc); oti; ++i, oti = oti->next)
;
return i;
return mono_image_alloc0 (class->image, size);
}
-static MonoRuntimeGenericContextOtherInfoTemplate*
+static MonoRuntimeGenericContextInfoTemplate*
alloc_oti (MonoImage *image)
{
static gboolean inited = FALSE;
static int num_allocted = 0;
static int num_bytes = 0;
- int size = sizeof (MonoRuntimeGenericContextOtherInfoTemplate);
+ int size = sizeof (MonoRuntimeGenericContextInfoTemplate);
if (!inited) {
mono_counters_register ("RGCTX oti num allocted", MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &num_allocted);
#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
+info_has_identity (MonoRgctxInfoType info_type)
+{
+ return info_type != MONO_RGCTX_INFO_CAST_CACHE;
+}
+
/*
* LOCKING: loader lock
*/
static void
-rgctx_template_set_other_slot (MonoImage *image, MonoRuntimeGenericContextTemplate *template, int type_argc,
- int slot, gpointer data, int info_type)
+rgctx_template_set_slot (MonoImage *image, MonoRuntimeGenericContextTemplate *template, int type_argc,
+ int slot, gpointer data, MonoRgctxInfoType info_type)
{
static gboolean inited = FALSE;
static int num_markers = 0;
static int num_data = 0;
int i;
- MonoRuntimeGenericContextOtherInfoTemplate *list = get_other_info_templates (template, type_argc);
- MonoRuntimeGenericContextOtherInfoTemplate **oti = &list;
+ MonoRuntimeGenericContextInfoTemplate *list = get_info_templates (template, type_argc);
+ MonoRuntimeGenericContextInfoTemplate **oti = &list;
if (!inited) {
mono_counters_register ("RGCTX oti num markers", MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &num_markers);
(*oti)->data = data;
(*oti)->info_type = info_type;
- set_other_info_templates (image, template, type_argc, list);
+ set_info_templates (image, template, type_argc, list);
if (data == MONO_RGCTX_SLOT_USED_MARKER)
++num_markers;
}
static gpointer
-inflate_other_data (gpointer data, int info_type, MonoGenericContext *context, MonoClass *class, gboolean temporary)
+inflate_info (MonoRuntimeGenericContextInfoTemplate *oti, MonoGenericContext *context, MonoClass *class, gboolean temporary)
{
+ gpointer data = oti->data;
+ MonoRgctxInfoType info_type = oti->info_type;
MonoError error;
g_assert (data);
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*/
return NULL;
}
-static gpointer
-inflate_other_info (MonoRuntimeGenericContextOtherInfoTemplate *oti,
- MonoGenericContext *context, MonoClass *class, gboolean temporary)
-{
- return inflate_other_data (oti->data, oti->info_type, context, class, temporary);
-}
-
static void
-free_inflated_info (int info_type, gpointer info)
+free_inflated_info (MonoRgctxInfoType info_type, gpointer info)
{
if (!info)
return;
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:
}
}
-static MonoRuntimeGenericContextOtherInfoTemplate
+static MonoRuntimeGenericContextInfoTemplate
class_get_rgctx_template_oti (MonoClass *class, int type_argc, guint32 slot, gboolean temporary, gboolean shared, gboolean *do_free);
static MonoClass*
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];
* mono_class_get_runtime_generic_context_template:
* @class: a class
*
- * Looks up or constructs, if necessary, the runtime generic context
- * for class.
+ * Looks up or constructs, if necessary, the runtime generic context template for class.
+ * The template is the same for all instantiations of a class.
*/
static MonoRuntimeGenericContextTemplate*
mono_class_get_runtime_generic_context_template (MonoClass *class)
MonoRuntimeGenericContextTemplate *parent_template, *template;
guint32 i;
+ class = get_shared_class (class);
+
mono_loader_lock ();
template = class_lookup_rgctx_template (class);
mono_loader_unlock ();
mono_loader_lock ();
if (class->parent) {
- if (class->parent->generic_class) {
- guint32 num_entries;
- int max_argc, type_argc;
+ guint32 num_entries;
+ int max_argc, type_argc;
- parent_template = mono_class_get_runtime_generic_context_template
- (class->parent->generic_class->container_class);
-
- max_argc = template_get_max_argc (parent_template);
-
- for (type_argc = 0; type_argc <= max_argc; ++type_argc) {
- num_entries = rgctx_template_num_other_infos (parent_template, type_argc);
-
- /* FIXME: quadratic! */
- for (i = 0; i < num_entries; ++i) {
- MonoRuntimeGenericContextOtherInfoTemplate oti;
-
- oti = class_get_rgctx_template_oti (class->parent, type_argc, i, FALSE, FALSE, NULL);
- if (oti.data && oti.data != MONO_RGCTX_SLOT_USED_MARKER) {
- rgctx_template_set_other_slot (class->image, template, type_argc, i,
- oti.data, oti.info_type);
- }
- }
- }
- } else {
- MonoRuntimeGenericContextOtherInfoTemplate *oti;
- int max_argc, type_argc;
+ parent_template = mono_class_get_runtime_generic_context_template (class->parent);
+ max_argc = template_get_max_argc (parent_template);
- parent_template = mono_class_get_runtime_generic_context_template (class->parent);
+ for (type_argc = 0; type_argc <= max_argc; ++type_argc) {
+ num_entries = rgctx_template_num_infos (parent_template, type_argc);
- max_argc = template_get_max_argc (parent_template);
+ /* FIXME: quadratic! */
+ for (i = 0; i < num_entries; ++i) {
+ MonoRuntimeGenericContextInfoTemplate oti;
- for (type_argc = 0; type_argc <= max_argc; ++type_argc) {
- /* FIXME: quadratic! */
- for (i = 0, oti = parent_template->other_infos; oti; ++i, oti = oti->next) {
- if (oti->data && oti->data != MONO_RGCTX_SLOT_USED_MARKER) {
- rgctx_template_set_other_slot (class->image, template, type_argc, i,
- oti->data, oti->info_type);
- }
+ oti = class_get_rgctx_template_oti (class->parent, type_argc, i, FALSE, FALSE, NULL);
+ if (oti.data && oti.data != MONO_RGCTX_SLOT_USED_MARKER) {
+ rgctx_template_set_slot (class->image, template, type_argc, i,
+ oti.data, oti.info_type);
}
}
}
}
/*
+ * class_get_rgctx_template_oti:
+ *
+ * Return the info template of CLASS numbered TYPE_ARGC/SLOT.
* temporary signifies whether the inflated info (oti.data) will be
* used temporarily, in which case it might be heap-allocated, or
* permanently, in which case it will be mempool-allocated. If
*
* LOCKING: loader lock
*/
-static MonoRuntimeGenericContextOtherInfoTemplate
+static MonoRuntimeGenericContextInfoTemplate
class_get_rgctx_template_oti (MonoClass *class, int type_argc, guint32 slot, gboolean temporary, gboolean shared, gboolean *do_free)
{
g_assert ((temporary && do_free) || (!temporary && !do_free));
+ DEBUG (printf ("get slot: %s %d\n", mono_type_full_name (&class->byval_arg), slot));
+
if (class->generic_class && !shared) {
- MonoRuntimeGenericContextOtherInfoTemplate oti;
+ MonoRuntimeGenericContextInfoTemplate oti;
gboolean tmp_do_free;
oti = class_get_rgctx_template_oti (class->generic_class->container_class,
type_argc, slot, TRUE, FALSE, &tmp_do_free);
if (oti.data) {
gpointer info = oti.data;
- oti.data = inflate_other_info (&oti, &class->generic_class->context, class, temporary);
+ oti.data = inflate_info (&oti, &class->generic_class->context, class, temporary);
if (tmp_do_free)
free_inflated_info (oti.info_type, info);
}
return oti;
} else {
MonoRuntimeGenericContextTemplate *template;
- MonoRuntimeGenericContextOtherInfoTemplate *oti;
+ MonoRuntimeGenericContextInfoTemplate *oti;
template = mono_class_get_runtime_generic_context_template (class);
oti = rgctx_template_get_other_slot (template, type_argc, slot);
}
static gpointer
-class_type_info (MonoDomain *domain, MonoClass *class, int info_type)
+class_type_info (MonoDomain *domain, MonoClass *class, MonoRgctxInfoType info_type)
{
switch (info_type) {
case MONO_RGCTX_INFO_STATIC_DATA: {
MonoVTable *vtable = mono_class_vtable (domain, class);
if (!vtable)
mono_raise_exception (mono_class_get_exception_for_failure (class));
- return vtable->data;
+ return mono_vtable_get_static_field_data (vtable);
}
case MONO_RGCTX_INFO_KLASS:
return 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 ();
}
}
static gpointer
-instantiate_other_info (MonoDomain *domain, MonoRuntimeGenericContextOtherInfoTemplate *oti,
+instantiate_info (MonoDomain *domain, MonoRuntimeGenericContextInfoTemplate *oti,
MonoGenericContext *context, MonoClass *class)
{
gpointer data;
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:
temporary = FALSE;
}
- data = inflate_other_info (oti, context, class, temporary);
+ data = inflate_info (oti, context, class, temporary);
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);
* LOCKING: loader lock
*/
static void
-fill_in_rgctx_template_slot (MonoClass *class, int type_argc, int index, gpointer data, int info_type)
+fill_in_rgctx_template_slot (MonoClass *class, int type_argc, int index, gpointer data, MonoRgctxInfoType info_type)
{
MonoRuntimeGenericContextTemplate *template = mono_class_get_runtime_generic_context_template (class);
MonoClass *subclass;
- rgctx_template_set_other_slot (class->image, template, type_argc, index, data, info_type);
+ rgctx_template_set_slot (class->image, template, type_argc, index, data, info_type);
/* Recurse for all subclasses */
if (generic_subclass_hash)
subclass = NULL;
while (subclass) {
- MonoRuntimeGenericContextOtherInfoTemplate subclass_oti;
+ MonoRuntimeGenericContextInfoTemplate subclass_oti;
MonoRuntimeGenericContextTemplate *subclass_template = class_lookup_rgctx_template (subclass);
g_assert (subclass_template);
}
}
+G_GNUC_UNUSED static const char*
+info_type_to_str (MonoRgctxInfoType type)
+{
+ switch (type) {
+ case MONO_RGCTX_INFO_STATIC_DATA: return "STATIC_DATA";
+ case MONO_RGCTX_INFO_KLASS: return "KLASS";
+ case MONO_RGCTX_INFO_VTABLE: return "VTABLE";
+ case MONO_RGCTX_INFO_TYPE: return "TYPE";
+ case MONO_RGCTX_INFO_REFLECTION_TYPE: return "REFLECTION_TYPE";
+ case MONO_RGCTX_INFO_METHOD: return "METHOD";
+ case MONO_RGCTX_INFO_GENERIC_METHOD_CODE: return "GENERIC_METHOD_CODE";
+ case MONO_RGCTX_INFO_CLASS_FIELD: return "CLASS_FIELD";
+ case MONO_RGCTX_INFO_METHOD_RGCTX: return "METHOD_RGCTX";
+ case MONO_RGCTX_INFO_METHOD_CONTEXT: return "METHOD_CONTEXT";
+ case MONO_RGCTX_INFO_REMOTING_INVOKE_WITH_CHECK: return "REMOTING_INVOKE_WITH_CHECK";
+ case MONO_RGCTX_INFO_METHOD_DELEGATE_CODE: return "METHOD_DELEGATE_CODE";
+ case MONO_RGCTX_INFO_CAST_CACHE: return "CAST_CACHE";
+ default:
+ return "<>";
+ }
+}
+
+G_GNUC_UNUSED static char*
+rgctx_info_to_str (MonoRgctxInfoType info_type, gpointer data)
+{
+ switch (info_type) {
+ case MONO_RGCTX_INFO_VTABLE:
+ return mono_type_full_name ((MonoType*)data);
+ default:
+ return g_strdup_printf ("<%p>", data);
+ }
+}
+
/*
* LOCKING: loader lock
*/
static int
-register_other_info (MonoClass *class, int type_argc, gpointer data, int info_type)
+register_info (MonoClass *class, int type_argc, gpointer data, MonoRgctxInfoType info_type)
{
int i;
MonoRuntimeGenericContextTemplate *template = mono_class_get_runtime_generic_context_template (class);
MonoClass *parent;
- MonoRuntimeGenericContextOtherInfoTemplate *oti;
+ MonoRuntimeGenericContextInfoTemplate *oti;
- for (i = 0, oti = get_other_info_templates (template, type_argc); oti; ++i, oti = oti->next) {
+ for (i = 0, oti = get_info_templates (template, type_argc); oti; ++i, oti = oti->next) {
if (!oti->data)
break;
}
- //g_print ("template %s . other_infos [%d] = %s\n", mono_type_get_full_name (class), i, mono_type_get_full_name (other_class));
+ DEBUG (printf ("set slot %s, infos [%d] = %s, %s\n", mono_type_get_full_name (class), i, info_type_to_str (info_type), rgctx_info_to_str (info_type, data)));
/* Mark the slot as used in all parent classes (until we find
a parent class which already has it marked used). */
parent = class->parent;
while (parent != NULL) {
MonoRuntimeGenericContextTemplate *parent_template;
- MonoRuntimeGenericContextOtherInfoTemplate *oti;
+ MonoRuntimeGenericContextInfoTemplate *oti;
if (parent->generic_class)
parent = parent->generic_class->container_class;
if (oti && oti->data)
break;
- rgctx_template_set_other_slot (parent->image, parent_template, type_argc, i,
- MONO_RGCTX_SLOT_USED_MARKER, 0);
+ rgctx_template_set_slot (parent->image, parent_template, type_argc, i,
+ MONO_RGCTX_SLOT_USED_MARKER, 0);
parent = parent->parent;
}
}
static gboolean
-other_info_equal (gpointer data1, gpointer data2, int info_type)
+info_equal (gpointer data1, gpointer data2, MonoRgctxInfoType info_type)
{
switch (info_type) {
case MONO_RGCTX_INFO_STATIC_DATA:
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:
}
static int
-lookup_or_register_other_info (MonoClass *class, int type_argc, gpointer data, int info_type,
+lookup_or_register_info (MonoClass *class, int type_argc, gpointer data, MonoRgctxInfoType info_type,
MonoGenericContext *generic_context)
{
static gboolean inited = FALSE;
MonoRuntimeGenericContextTemplate *rgctx_template =
mono_class_get_runtime_generic_context_template (class);
- MonoRuntimeGenericContextOtherInfoTemplate *oti_list, *oti;
+ MonoRuntimeGenericContextInfoTemplate *oti_list, *oti;
int i;
+ class = get_shared_class (class);
+
mono_loader_lock ();
- oti_list = get_other_info_templates (rgctx_template, type_argc);
+ if (info_has_identity (info_type)) {
+ oti_list = get_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_info (oti, generic_context, class, TRUE);
- if (other_info_equal (data, inflated_data, info_type)) {
+ if (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 */
- i = register_other_info (class, type_argc, data, info_type);
+ i = register_info (class, type_argc, data, info_type);
mono_loader_unlock ();
}
/*
- * mono_method_lookup_or_register_other_info:
+ * mono_method_lookup_or_register_info:
* @method: a method
* @in_mrgctx: whether to put the data into the MRGCTX
* @data: the info data
* @info_type: the type of info to register about data
* @generic_context: a generic context
*
- * Looks up and, if necessary, adds information about other_class in
+ * Looks up and, if necessary, adds information about data/info_type in
* method's or method's class runtime generic context. Returns the
* encoded slot number.
*/
guint32
-mono_method_lookup_or_register_other_info (MonoMethod *method, gboolean in_mrgctx, gpointer data,
- int info_type, MonoGenericContext *generic_context)
+mono_method_lookup_or_register_info (MonoMethod *method, gboolean in_mrgctx, gpointer data,
+ MonoRgctxInfoType info_type, MonoGenericContext *generic_context)
{
MonoClass *class = method->klass;
int type_argc, index;
type_argc = 0;
}
- index = lookup_or_register_other_info (class, type_argc, data, info_type, generic_context);
+ index = lookup_or_register_info (class, type_argc, data, info_type, generic_context);
//g_print ("rgctx item at index %d argc %d\n", index, type_argc);
MonoDomain *domain = class_vtable->domain;
MonoClass *class = class_vtable->klass;
MonoGenericContext *class_context = class->generic_class ? &class->generic_class->context : NULL;
- MonoRuntimeGenericContextOtherInfoTemplate oti;
+ MonoRuntimeGenericContextInfoTemplate oti;
MonoGenericContext context = { class_context ? class_context->class_inst : NULL, method_inst };
int rgctx_index;
gboolean do_free;
oti = class_get_rgctx_template_oti (get_shared_class (class),
method_inst ? method_inst->type_argc : 0, slot, TRUE, TRUE, &do_free);
/* This might take the loader lock */
- info = instantiate_other_info (domain, &oti, &context, class);
+ info = instantiate_info (domain, &oti, &context, class);
/*
if (method_inst)
* @class_vtable: a vtable
* @slot: a slot index to be instantiated
*
- * Instantiates a slot in the RGCTX.
+ * Instantiates a slot in the RGCTX, returning its value.
*/
gpointer
mono_class_fill_runtime_generic_context (MonoVTable *class_vtable, guint32 slot)
info = fill_runtime_generic_context (class_vtable, rgctx, slot, 0);
+ DEBUG (printf ("get rgctx slot: %s %d -> %p\n", mono_type_full_name (&class_vtable->klass->byval_arg), slot, info));
+
return info;
}
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;
+}