Merge pull request #451 from madewokherd/wrappertrace
[mono.git] / mono / mini / mini-generic-sharing.c
index 28a472bfc72d89302e1d58657088e176d6295143..079c88f71f68e3af3a4d3b7e4c37868c5844f0cb 100644 (file)
@@ -4,7 +4,8 @@
  * 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);
@@ -113,12 +120,12 @@ mono_class_check_context_used (MonoClass *class)
 /*
  * 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);
 }
 
@@ -126,12 +133,12 @@ get_other_info_templates (MonoRuntimeGenericContextTemplate *template, int type_
  * 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;
@@ -160,15 +167,15 @@ template_get_max_argc (MonoRuntimeGenericContextTemplate *template)
 /*
  * 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;
        }
@@ -180,12 +187,12 @@ rgctx_template_get_other_slot (MonoRuntimeGenericContextTemplate *template, int
  * 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;
@@ -336,14 +343,14 @@ alloc_template (MonoClass *class)
        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);
@@ -359,20 +366,31 @@ alloc_oti (MonoImage *image)
 
 #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);
@@ -396,7 +414,7 @@ rgctx_template_set_other_slot (MonoImage *image, MonoRuntimeGenericContextTempla
        (*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;
@@ -479,8 +497,10 @@ mono_class_get_method_generic (MonoClass *klass, MonoMethod *method)
 }
 
 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);
@@ -494,7 +514,8 @@ inflate_other_data (gpointer data, int info_type, MonoGenericContext *context, M
        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*/
@@ -552,15 +573,8 @@ inflate_other_data (gpointer data, int info_type, MonoGenericContext *context, M
        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;
@@ -571,6 +585,7 @@ free_inflated_info (int info_type, gpointer info)
        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:
@@ -578,7 +593,7 @@ free_inflated_info (int info_type, gpointer info)
        }
 }
 
-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*
@@ -593,17 +608,8 @@ 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];
 
@@ -700,8 +706,8 @@ get_shared_class (MonoClass *class)
  * 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)
@@ -709,6 +715,8 @@ 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 ();
@@ -723,44 +731,23 @@ mono_class_get_runtime_generic_context_template (MonoClass *class)
        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);
                                }
                        }
                }
@@ -782,6 +769,9 @@ mono_class_get_runtime_generic_context_template (MonoClass *class)
 }
 
 /*
+ * 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
@@ -790,20 +780,22 @@ mono_class_get_runtime_generic_context_template (MonoClass *class)
  *
  * 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);
                }
@@ -813,7 +805,7 @@ class_get_rgctx_template_oti (MonoClass *class, int type_argc, guint32 slot, gbo
                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);
@@ -827,14 +819,14 @@ class_get_rgctx_template_oti (MonoClass *class, int type_argc, guint32 slot, gbo
 }
 
 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;
@@ -844,6 +836,12 @@ class_type_info (MonoDomain *domain, MonoClass *class, int info_type)
                        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 ();
        }
@@ -852,7 +850,7 @@ class_type_info (MonoDomain *domain, MonoClass *class, int info_type)
 }
 
 static gpointer
-instantiate_other_info (MonoDomain *domain, MonoRuntimeGenericContextOtherInfoTemplate *oti,
+instantiate_info (MonoDomain *domain, MonoRuntimeGenericContextInfoTemplate *oti,
        MonoGenericContext *context, MonoClass *class)
 {
        gpointer data;
@@ -865,18 +863,20 @@ instantiate_other_info (MonoDomain *domain, MonoRuntimeGenericContextOtherInfoTe
        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);
@@ -939,12 +939,12 @@ instantiate_other_info (MonoDomain *domain, MonoRuntimeGenericContextOtherInfoTe
  * 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)
@@ -953,7 +953,7 @@ fill_in_rgctx_template_slot (MonoClass *class, int type_argc, int index, gpointe
                subclass = NULL;
 
        while (subclass) {
-               MonoRuntimeGenericContextOtherInfoTemplate subclass_oti;
+               MonoRuntimeGenericContextInfoTemplate subclass_oti;
                MonoRuntimeGenericContextTemplate *subclass_template = class_lookup_rgctx_template (subclass);
 
                g_assert (subclass_template);
@@ -967,30 +967,63 @@ fill_in_rgctx_template_slot (MonoClass *class, int type_argc, int index, gpointe
        }
 }
 
+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;
@@ -1001,8 +1034,8 @@ register_other_info (MonoClass *class, int type_argc, gpointer data, int info_ty
                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;
        }
@@ -1015,7 +1048,7 @@ register_other_info (MonoClass *class, int type_argc, gpointer data, int info_ty
 }
 
 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:
@@ -1023,6 +1056,7 @@ other_info_equal (gpointer data1, gpointer data2, int info_type)
        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:
@@ -1040,7 +1074,7 @@ other_info_equal (gpointer data1, gpointer data2, int info_type)
 }
 
 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;
@@ -1048,31 +1082,35 @@ lookup_or_register_other_info (MonoClass *class, int type_argc, gpointer data, i
 
        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 ();
 
@@ -1087,20 +1125,20 @@ lookup_or_register_other_info (MonoClass *class, int type_argc, gpointer data, i
 }
 
 /*
- * 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;
@@ -1115,7 +1153,7 @@ mono_method_lookup_or_register_other_info (MonoMethod *method, gboolean in_mrgct
                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);
 
@@ -1188,7 +1226,7 @@ fill_runtime_generic_context (MonoVTable *class_vtable, MonoRuntimeGenericContex
        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;
@@ -1235,7 +1273,7 @@ fill_runtime_generic_context (MonoVTable *class_vtable, MonoRuntimeGenericContex
        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)
@@ -1265,7 +1303,7 @@ fill_runtime_generic_context (MonoVTable *class_vtable, MonoRuntimeGenericContex
  * @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)
@@ -1295,6 +1333,8 @@ 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;
 }
 
@@ -1863,3 +1903,14 @@ mono_generic_sharing_cleanup (void)
        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;
+}