2008-04-28 Mark Probst <mark.probst@gmail.com>
authorMark Probst <mark.probst@gmail.com>
Mon, 28 Apr 2008 14:49:23 +0000 (14:49 -0000)
committerMark Probst <mark.probst@gmail.com>
Mon, 28 Apr 2008 14:49:23 +0000 (14:49 -0000)
* class-internals.h, generic-sharing.c: New, small runtime generic context.

* metadata-internals.h, domain.c, image.c: Less bookkeeping is required for the new RGCTX.

* object.c: Don't setup the RGCTX when the vtable is created,
because we're setting it up lazily now.

2008-04-28  Mark Probst  <mark.probst@gmail.com>

* mini.h, mini.c: Lots of code for accessing the old RGCTX
deleted.  The only way to access the new RGCTX is via the
trampline.

* mini.c, mini-amd64, mini-x86.c, mini-exceptions.c: Pass the
vtable instead of the RGCTX to static methods.

* mini-tramplines.c, tramp-amd64.c, tramp-x86.c: Trampoline for
accessing the new RGCTX.

* generic-sharing.c: There is no separation between self, type
arguments and other types in the RGCTX anymore.

svn path=/trunk/mono/; revision=102043

17 files changed:
mono/metadata/ChangeLog
mono/metadata/class-internals.h
mono/metadata/domain.c
mono/metadata/generic-sharing.c
mono/metadata/image.c
mono/metadata/metadata-internals.h
mono/metadata/object.c
mono/mini/ChangeLog
mono/mini/generic-sharing.c
mono/mini/mini-amd64.c
mono/mini/mini-exceptions.c
mono/mini/mini-trampolines.c
mono/mini/mini-x86.c
mono/mini/mini.c
mono/mini/mini.h
mono/mini/tramp-amd64.c
mono/mini/tramp-x86.c

index 3f595486bdbd98cbe1b42ad44bec4ac57bad4f57..d9f82d3b9256b112f34623af0ec3d5f3aeb9b4f4 100644 (file)
@@ -1,3 +1,12 @@
+2008-04-28  Mark Probst  <mark.probst@gmail.com>
+
+       * class-internals.h, generic-sharing.c: New, small runtime generic context.
+
+       * metadata-internals.h, domain.c, image.c: Less bookkeeping is required for the new RGCTX.
+
+       * object.c: Don't setup the RGCTX when the vtable is created,
+       because we're setting it up lazily now.
+
 2008-04-26  Zoltan Varga  <vargaz@gmail.com>
 
        * sgen-gc.c: Make the 'desc' variables an mword instead of a guint32 to fix 
index 631393c1b2a8279b6918a728c8e9b413f22d5123..d8b2fa8a458dd3444edca5f7f6b38a0c0fef953e 100644 (file)
@@ -190,15 +190,15 @@ typedef struct {
        MonoVTable *domain_vtables [MONO_ZERO_LEN_ARRAY];
 } MonoClassRuntimeInfo;
 
-#define MONO_RGCTX_MAX_OTHER_INFOS     2
-
 enum {
        MONO_RGCTX_INFO_STATIC_DATA,
        MONO_RGCTX_INFO_KLASS,
        MONO_RGCTX_INFO_VTABLE,
+       MONO_RGCTX_INFO_TYPE,
        MONO_RGCTX_INFO_REFLECTION_TYPE,
        MONO_RGCTX_INFO_METHOD,
-       MONO_RGCTX_INFO_GENERIC_METHOD_CODE
+       MONO_RGCTX_INFO_GENERIC_METHOD_CODE,
+       MONO_RGCTX_INFO_CLASS_FIELD
 };
 
 typedef struct _MonoRuntimeGenericContextOtherInfoTemplate {
@@ -208,10 +208,8 @@ typedef struct _MonoRuntimeGenericContextOtherInfoTemplate {
 } MonoRuntimeGenericContextOtherInfoTemplate;
 
 typedef struct {
-       int num_arg_infos;
        MonoClass *next_subclass;
        MonoRuntimeGenericContextOtherInfoTemplate *other_infos;
-       MonoType *arg_infos [MONO_ZERO_LEN_ARRAY];
 } MonoRuntimeGenericContextTemplate;
 
 struct _MonoClass {
@@ -351,37 +349,7 @@ struct _MonoClass {
 #define MONO_CLASS_IMPLEMENTS_INTERFACE(k,uiid) (((uiid) <= (k)->max_interface_id) && ((k)->interface_bitmap [(uiid) >> 3] & (1 << ((uiid)&7))))
 int mono_class_interface_offset (MonoClass *klass, MonoClass *itf);
 
-typedef struct {
-       gpointer static_data;
-       MonoClass *klass;
-       MonoVTable *vtable;
-} MonoRuntimeGenericSuperInfo;
-
-typedef struct {
-       gpointer static_data;
-       MonoClass *klass;
-       MonoVTable *vtable;
-} MonoRuntimeGenericArgInfo;
-
-typedef struct {
-       MonoDomain *domain;
-       MonoVTable *vtable;
-       gpointer other_infos [MONO_RGCTX_MAX_OTHER_INFOS];
-       gpointer *extra_other_infos;
-       MonoRuntimeGenericArgInfo arg_infos [MONO_ZERO_LEN_ARRAY];
-} MonoRuntimeGenericContext;
-
-#define MONO_RGCTX_ENCODE_DIRECT_OFFSET(o)     ((guint32)(o) & 0x00ffffff)
-#define MONO_RGCTX_ENCODE_INDIRECT_OFFSET(o)   (((guint32)(o) & 0x00ffffff) | 0x01000000)
-
-#define MONO_RGCTX_OFFSET_INDIRECT_SLOT(s)     ((gint32)(((guint32)(s))>>24) - 1)
-#define MONO_RGCTX_OFFSET_IS_INDIRECT(s)       (MONO_RGCTX_OFFSET_INDIRECT_SLOT((s)) >= 0)
-
-#define MONO_RGCTX_OFFSET_OFFSET_PART(s)       ((guint32)(s) & 0x00ffffff)
-#define MONO_RGCTX_OFFSET_DIRECT_OFFSET(s)     ((MONO_RGCTX_OFFSET_OFFSET_PART((s)) & 0x00800000) ? \
-                       (gint32)(MONO_RGCTX_OFFSET_OFFSET_PART((s)) | 0xff000000) : \
-                       (gint32)MONO_RGCTX_OFFSET_OFFSET_PART((s)))
-#define MONO_RGCTX_OFFSET_INDIRECT_OFFSET(s)    MONO_RGCTX_OFFSET_DIRECT_OFFSET((s))
+typedef gpointer MonoRuntimeGenericContext;
 
 /* the interface_offsets array is stored in memory before this struct */
 struct MonoVTable {
@@ -973,14 +941,11 @@ mono_type_get_basic_type_from_generic (MonoType *type) MONO_INTERNAL;
 gboolean
 mono_class_generic_sharing_enabled (MonoClass *class) MONO_INTERNAL;
 
-MonoRuntimeGenericContextTemplate*
-mono_class_get_runtime_generic_context_template (MonoClass *class) MONO_INTERNAL;
-
-void
-mono_class_setup_runtime_generic_context (MonoClass *class, MonoDomain *domain) MONO_INTERNAL;
+gpointer
+mono_class_fill_runtime_generic_context (MonoVTable *class_vtable, guint32 slot) MONO_INTERNAL;
 
-void
-mono_class_fill_runtime_generic_context (MonoRuntimeGenericContext *rgctx) MONO_INTERNAL;
+int
+mono_class_rgctx_get_array_size (int n) MONO_INTERNAL;
 
 gboolean
 mono_class_lookup_or_register_other_info (MonoClass *class, gpointer data, int info_type, MonoGenericContext *generic_context) MONO_INTERNAL;
@@ -994,9 +959,6 @@ mono_class_check_context_used (MonoClass *class) MONO_INTERNAL;
 void
 mono_class_unregister_image_generic_subclasses (MonoImage *image) MONO_INTERNAL;
 
-void
-mono_class_unregister_domain_generic_vtables (MonoDomain *domain) MONO_INTERNAL;
-
 gboolean
 mono_method_can_access_method_full (MonoMethod *method, MonoMethod *called, MonoClass *context_klass) MONO_INTERNAL;
 
index 267a82031e7db1366059dbc39b34cc12083873f9..4c20222b99acc57569feed6eb585f35f4226536d 100644 (file)
@@ -1816,8 +1816,6 @@ mono_domain_free (MonoDomain *domain, gboolean force)
        max_domain_code_alloc = MAX (max_domain_code_alloc, code_alloc);
        max_domain_code_size = MAX (max_domain_code_size, code_size);
 
-       mono_class_unregister_domain_generic_vtables (domain);
-
 #ifdef DEBUG_DOMAIN_UNLOAD
        mono_mempool_invalidate (domain->mp);
        mono_code_manager_invalidate (domain->code_mp);
index a39bc78503568ce78c6d67fa4468a315de358d89..dcce66701191d71410cd43e17857cf60489e9d37 100644 (file)
 #include <glib.h>
 #endif
 #include <mono/utils/mono-membar.h>
+#include <mono/utils/mono-counters.h>
 
 #include "metadata-internals.h"
 #include "class.h"
 #include "class-internals.h"
+#include "marshal.h"
 
 static int
 type_check_context_used (MonoType *type, gboolean recursive)
@@ -165,13 +167,6 @@ rgctx_template_num_other_infos (MonoRuntimeGenericContextTemplate *template)
        return i;
 }
 
-/* Maps from uninstantiated generic classes to GSLists's of
- * MonoVTable's of classes that are instantiations of the key class.
- *
- * LOCKING: templates lock
- */
-static GHashTable *generic_class_rgctx_hash;
-
 /* Maps from uninstantiated generic classes to GList's of
  * uninstantiated generic classes whose parent is the key class or an
  * instance of the key class.
@@ -180,18 +175,6 @@ static GHashTable *generic_class_rgctx_hash;
  */
 static GHashTable *generic_subclass_hash;
 
-static void
-list_hash_table_insert (GHashTable **hash, gpointer key, gpointer value)
-{
-       GSList *list;
-
-       if (!*hash)
-               *hash = g_hash_table_new (mono_aligned_addr_hash, NULL);
-
-       list = g_hash_table_lookup (*hash, key);
-       g_hash_table_insert (*hash, key, g_slist_prepend (list, value));
-}
-
 /*
  * LOCKING: templates lock
  */
@@ -220,34 +203,6 @@ class_lookup_rgctx_template (MonoClass *class)
        return template;
 }
 
-/*
- * LOCKING: templates lock
- */
-static void
-register_open_instance (MonoClass *class)
-{
-       g_assert (class->generic_class && class->generic_class->container_class);
-       g_assert (class_lookup_rgctx_template (class));
-
-       list_hash_table_insert (&class->image->generic_class_open_instances_hash, class->generic_class->container_class, class);
-}
-
-/*
- * LOCKING: templates lock
- */
-static void
-register_rgctx_vtable (MonoVTable *vtable)
-{
-       MonoClass *class = vtable->klass;
-
-       if (class->generic_class)
-               class = class->generic_class->container_class;
-
-       //g_print ("registering rgctx %p for class %s (%p)\n", vtable, mono_type_get_full_name (class), class);
-
-       list_hash_table_insert (&generic_class_rgctx_hash, class, vtable);
-}
-
 /*
  * LOCKING: templates lock
  */
@@ -336,52 +291,52 @@ mono_class_unregister_image_generic_subclasses (MonoImage *image)
        g_hash_table_destroy (old_hash);
 }
 
-static void
-move_vtables_not_in_domain_foreach_func (MonoClass *class, GSList *list, MonoDomain *domain)
+/*
+ * LOCKING: loader lock
+ */
+static MonoRuntimeGenericContextTemplate*
+alloc_template (MonoClass *class)
 {
-       GSList *new_list = NULL;
-       GSList *iter = list;
-
-       while (iter) {
-               MonoVTable *vtable = iter->data;
+       static gboolean inited = FALSE;
+       static int num_allocted = 0;
+       static int num_bytes = 0;
 
-               if (vtable->domain != domain)
-                       new_list = g_slist_prepend (new_list, vtable);
+       int size = sizeof (MonoRuntimeGenericContextTemplate);
 
-               iter = iter->next;
+       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;
        }
 
-       g_slist_free (list);
+       num_allocted++;
+       num_bytes += size;
 
-       if (new_list)
-               g_hash_table_insert (generic_class_rgctx_hash, class, new_list);
+       return mono_mempool_alloc0 (class->image->mempool, size);
 }
 
 /*
- * mono_class_unregister_domain_generic_vtables:
- * @domain: a domain
- *
- * Removes all vtables of the domain from the generic vtables hash.
- * Must be called when a domain is destroyed.
+ * LOCKING: loader lock
  */
-void
-mono_class_unregister_domain_generic_vtables (MonoDomain *domain)
+static MonoRuntimeGenericContextOtherInfoTemplate*
+alloc_oti (MonoImage *image)
 {
-       GHashTable *old_hash;
-
-       if (!generic_class_rgctx_hash)
-               return;
+       static gboolean inited = FALSE;
+       static int num_allocted = 0;
+       static int num_bytes = 0;
 
-       templates_lock ();
+       int size = sizeof (MonoRuntimeGenericContextOtherInfoTemplate);
 
-       old_hash = generic_class_rgctx_hash;
-       generic_class_rgctx_hash = g_hash_table_new (mono_aligned_addr_hash, NULL);
+       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;
+       }
 
-       g_hash_table_foreach (old_hash, (GHFunc)move_vtables_not_in_domain_foreach_func, domain);
+       num_allocted++;
+       num_bytes += size;
 
-       templates_unlock ();
-
-       g_hash_table_destroy (old_hash);
+       return mono_mempool_alloc0 (image->mempool, size);
 }
 
 /*
@@ -395,6 +350,7 @@ rgctx_template_set_other_slot (MonoImage *image, MonoRuntimeGenericContextTempla
        MonoRuntimeGenericContextOtherInfoTemplate **oti;
 
        g_assert (slot >= 0);
+       g_assert (data);
 
        mono_loader_lock ();
 
@@ -404,7 +360,7 @@ rgctx_template_set_other_slot (MonoImage *image, MonoRuntimeGenericContextTempla
                if (i > 0)
                        oti = &(*oti)->next;
                if (!*oti)
-                       *oti = mono_mempool_alloc0 (image->mempool, sizeof (MonoRuntimeGenericContextOtherInfoTemplate));
+                       *oti = alloc_oti (image);
                ++i;
        }
 
@@ -415,26 +371,6 @@ rgctx_template_set_other_slot (MonoImage *image, MonoRuntimeGenericContextTempla
        mono_loader_unlock ();
 }
 
-static gboolean
-include_arg_info (MonoType *type, MonoRuntimeGenericContextTemplate *parent_template)
-{
-       int i;
-
-       if (!MONO_TYPE_IS_REFERENCE (type) &&
-                       mono_type_get_type (type) != MONO_TYPE_VAR &&
-                       mono_type_get_type (type) != MONO_TYPE_MVAR)
-               return FALSE;
-
-       if (!parent_template)
-               return TRUE;
-
-       for (i = 0; i < parent_template->num_arg_infos; ++i)
-               if (type == parent_template->arg_infos [i])
-                       return FALSE;
-
-       return TRUE;
-}
-
 #define MONO_RGCTX_SLOT_USED_MARKER    ((gpointer)&mono_defaults.object_class->byval_arg)
 
 static gpointer
@@ -450,12 +386,37 @@ inflate_other_data (gpointer data, int info_type, MonoGenericContext *context)
        case MONO_RGCTX_INFO_STATIC_DATA:
        case MONO_RGCTX_INFO_KLASS:
        case MONO_RGCTX_INFO_VTABLE:
+       case MONO_RGCTX_INFO_TYPE:
        case MONO_RGCTX_INFO_REFLECTION_TYPE:
                return mono_class_inflate_generic_type (data, context);
 
        case MONO_RGCTX_INFO_METHOD:
-       case MONO_RGCTX_INFO_GENERIC_METHOD_CODE:
-               return mono_class_inflate_generic_method (data, context);
+       case MONO_RGCTX_INFO_GENERIC_METHOD_CODE: {
+               MonoMethod *method = data;
+
+               if (method->wrapper_type != MONO_WRAPPER_NONE) {
+                       g_assert (method->wrapper_type == MONO_WRAPPER_STATIC_RGCTX_INVOKE);
+
+                       method = mono_marshal_method_from_wrapper (method);
+                       method = mono_class_inflate_generic_method (method, context);
+                       method = mono_marshal_get_static_rgctx_invoke (method);
+               }
+
+               return mono_class_inflate_generic_method (method, context);
+       }
+
+       case MONO_RGCTX_INFO_CLASS_FIELD: {
+               MonoClassField *field = data;
+               MonoType *inflated_type = mono_class_inflate_generic_type (&field->parent->byval_arg, context);
+               MonoClass *inflated_class = mono_class_from_mono_type (inflated_type);
+               int i = field - field->parent->fields;
+               gpointer dummy;
+
+               mono_class_get_fields (inflated_class, &dummy);
+               g_assert (inflated_class->fields);
+
+               return &inflated_class->fields [i];
+       }
 
        default:
                g_assert_not_reached ();
@@ -468,6 +429,9 @@ inflate_other_info (MonoRuntimeGenericContextOtherInfoTemplate *oti, MonoGeneric
        return inflate_other_data (oti->data, oti->info_type, context);
 }
 
+static MonoRuntimeGenericContextOtherInfoTemplate
+class_get_rgctx_template_oti (MonoClass *class, guint32 slot);
+
 /*
  * mono_class_get_runtime_generic_context_template:
  * @class: a class
@@ -475,14 +439,14 @@ inflate_other_info (MonoRuntimeGenericContextOtherInfoTemplate *oti, MonoGeneric
  * Looks up or constructs, if necessary, the runtime generic context
  * for class.
  */
-MonoRuntimeGenericContextTemplate*
+static MonoRuntimeGenericContextTemplate*
 mono_class_get_runtime_generic_context_template (MonoClass *class)
 {
-       int num_parent_args, num_class_args, total_num_args;
        MonoRuntimeGenericContextTemplate *parent_template, *template;
        MonoGenericInst *inst;
-       int i, j;
-       MonoRuntimeGenericContextOtherInfoTemplate *oti;
+       guint32 i;
+
+       g_assert (!class->generic_class);
 
        templates_lock ();
        template = class_lookup_rgctx_template (class);
@@ -491,122 +455,50 @@ mono_class_get_runtime_generic_context_template (MonoClass *class)
        if (template)
                return template;
 
-       if (class->generic_class) {
-               parent_template = mono_class_get_runtime_generic_context_template (class->generic_class->container_class);
-
-               mono_loader_lock ();
-               template = mono_mempool_alloc0 (class->image->mempool,
-                       sizeof (MonoRuntimeGenericContextTemplate) + sizeof (MonoType*) * parent_template->num_arg_infos);
-               mono_loader_unlock ();
-
-               template->num_arg_infos = parent_template->num_arg_infos;
-
-               for (i = 0; i < parent_template->num_arg_infos; ++i) {
-                       template->arg_infos [i] = mono_class_inflate_generic_type (parent_template->arg_infos [i],
-                               &class->generic_class->context);
-                       /*
-                       g_print("arg info %d of %s is %s (from %s)\n", i,
-                               mono_type_get_full_name (class),
-                               mono_type_get_name (template->arg_infos [i]),
-                               mono_type_get_name (parent_template->arg_infos [i]));
-                       */
-               }
-
-               /* 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, i,
-                                       inflate_other_info (oti, &class->generic_class->context),
-                                       oti->info_type);
-                       }
-               }
-
-               templates_lock ();
-
-               if (class_lookup_rgctx_template (class)) {
-                       /* some other thread already set the template */
-                       template = class_lookup_rgctx_template (class);
-               } else {
-                       class_set_rgctx_template (class, template);
-                       register_open_instance (class);
-               }
-
-               templates_unlock ();
-
-               return template;
-       }
-
-       if (class->parent)
-               parent_template = mono_class_get_runtime_generic_context_template (class->parent);
-       else
-               parent_template = NULL;
-
-       if (parent_template)
-               num_parent_args = parent_template->num_arg_infos;
-       else
-               num_parent_args = 0;
-
        if (class->generic_container)
                inst = class->generic_container->context.class_inst;
        else
                inst = NULL;
 
-       num_class_args = 0;
-       if (inst) {
-               for (i = 0; i < inst->type_argc; ++i) {
-                       if (include_arg_info (inst->type_argv [i], parent_template))
-                               ++num_class_args;
-               }
-       }
-
-       total_num_args = num_parent_args + num_class_args;
-
        mono_loader_lock ();
-       template = mono_mempool_alloc0 (class->image->mempool,
-               sizeof (MonoRuntimeGenericContextTemplate) + sizeof (MonoType*) * total_num_args);
+       template = alloc_template (class);
        mono_loader_unlock ();
 
-       template->num_arg_infos = total_num_args;
+       if (class->parent) {
+               if (class->parent->generic_class) {
+                       guint32 num_entries;
 
-       if (num_parent_args > 0)
-               memcpy (template->arg_infos, parent_template->arg_infos,
-                       sizeof (MonoType*) * parent_template->num_arg_infos);
+                       parent_template = mono_class_get_runtime_generic_context_template
+                               (class->parent->generic_class->container_class);
+                       num_entries = rgctx_template_num_other_infos (parent_template);
 
-       j = 0;
-       if (inst) {
-               for (i = 0; i < inst->type_argc; ++i) {
-                       MonoType *type = inst->type_argv [i];
+                       mono_loader_lock ();
 
-                       if (include_arg_info (type, parent_template))
-                               template->arg_infos [num_parent_args + j++] = type;
-               }
-       }
-       g_assert (j == num_class_args);
+                       /* FIXME: quadratic! */
+                       for (i = 0; i < num_entries; ++i) {
+                               MonoRuntimeGenericContextOtherInfoTemplate oti;
 
-       /*
-       g_print ("class %s has %d type args (%d from parent)\n",
-               mono_type_get_full_name(class), total_num_args, num_parent_args);
-       */
+                               oti = class_get_rgctx_template_oti (class->parent, i);
+                               if (oti.data && oti.data != MONO_RGCTX_SLOT_USED_MARKER)
+                                       rgctx_template_set_other_slot (class->image, template, i, oti.data, oti.info_type);
+                       }
 
-       if (parent_template) {
-               MonoRuntimeGenericContextOtherInfoTemplate *oti, **new_oti;
+                       mono_loader_unlock ();
+               } else {
+                       MonoRuntimeGenericContextOtherInfoTemplate *oti;
 
-               oti = parent_template->other_infos;
-               new_oti = &template->other_infos;
+                       parent_template = mono_class_get_runtime_generic_context_template (class->parent);
 
-               mono_loader_lock ();
+                       mono_loader_lock ();
 
-               while (oti) {
-                       *new_oti = mono_mempool_alloc0 (class->image->mempool,
-                               sizeof (MonoRuntimeGenericContextOtherInfoTemplate));
-                       (*new_oti)->data = oti->data;
-                       (*new_oti)->info_type = oti->info_type;
+                       /* 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, i, oti->data, oti->info_type);
+                       }
 
-                       oti = oti->next;
-                       new_oti = &(*new_oti)->next;
+                       mono_loader_unlock ();
                }
-
-               mono_loader_unlock ();
        }
 
        templates_lock ();
@@ -626,6 +518,34 @@ mono_class_get_runtime_generic_context_template (MonoClass *class)
        return template;
 }
 
+static MonoRuntimeGenericContextOtherInfoTemplate
+class_get_rgctx_template_oti (MonoClass *class, guint32 slot)
+{
+       if (class->generic_class) {
+               MonoRuntimeGenericContextOtherInfoTemplate oti;
+
+               oti = class_get_rgctx_template_oti (class->generic_class->container_class, slot);
+               if (oti.data)
+                       oti.data = inflate_other_info (&oti, &class->generic_class->context);
+
+               return oti;
+       } else {
+               MonoRuntimeGenericContextTemplate *template;
+               MonoRuntimeGenericContextOtherInfoTemplate *oti;
+               guint32 i;
+
+               template = mono_class_get_runtime_generic_context_template (class);
+
+               for (i = 0, oti = template->other_infos; oti; ++i, oti = oti->next) {
+                       if (i == slot)
+                               break;
+               }
+               g_assert (i == slot && oti);
+
+               return *oti;
+       }
+}
+
 static MonoClass*
 class_uninstantiated (MonoClass *class)
 {
@@ -669,12 +589,16 @@ instantiate_other_info (MonoDomain *domain, MonoRuntimeGenericContextOtherInfoTe
 
                return class_type_info (domain, arg_class, oti->info_type);
        }
+       case MONO_RGCTX_INFO_TYPE:
+               return data;
        case MONO_RGCTX_INFO_REFLECTION_TYPE:
                return mono_type_get_object (domain, data);
        case MONO_RGCTX_INFO_METHOD:
                return data;
        case MONO_RGCTX_INFO_GENERIC_METHOD_CODE:
                return mono_compile_method (data);
+       case MONO_RGCTX_INFO_CLASS_FIELD:
+               return data;
        default:
                g_assert_not_reached ();
        }
@@ -688,8 +612,7 @@ fill_in_rgctx_template_slot (MonoClass *class, int index, gpointer data, int inf
 {
        MonoRuntimeGenericContextTemplate *template = mono_class_get_runtime_generic_context_template (class);
        MonoClass *subclass;
-       GSList *instances;
-       int old_length, new_length, old_instances_extra_length;
+       int old_length, new_length;
        int old_instances_length = -1;
 
        g_assert (!class->generic_class);
@@ -698,43 +621,8 @@ fill_in_rgctx_template_slot (MonoClass *class, int index, gpointer data, int inf
        rgctx_template_set_other_slot (class->image, template, index, data, info_type);
        new_length = rgctx_template_num_other_infos (template);
 
-       /* For all open instantiations on this level: Instantiate the
-        * type and put it in the rgctx template.
-        */
-       if (class->image->generic_class_open_instances_hash)
-               instances = g_hash_table_lookup (class->image->generic_class_open_instances_hash, class);
-       else
-               instances = NULL;
-
-       while (instances) {
-               MonoClass *instance = instances->data;
-               MonoRuntimeGenericContextTemplate *instance_template = class_lookup_rgctx_template (instance);
-               int length;
-               gpointer inflated_data;
-
-               g_assert (instance_template);
-               g_assert (instance->generic_class != NULL && instance->generic_class->container_class == class);
-
-               length = rgctx_template_num_other_infos (instance_template);
-               if (old_instances_length < 0)
-                       old_instances_length = length;
-
-               g_assert (length == old_instances_length);
-
-               inflated_data = inflate_other_data (data, info_type, &instance->generic_class->context);
-               rgctx_template_set_other_slot (instance->image, instance_template, index,
-                       inflated_data, info_type);
-
-               g_assert (rgctx_template_num_other_infos (instance_template) == new_length);
-
-               instances = instances->next;
-       }
-
        if (old_instances_length < 0)
                old_instances_length = old_length;
-       old_instances_extra_length = MAX(old_instances_length - MONO_RGCTX_MAX_OTHER_INFOS, 0);
-
-       g_assert (old_instances_length <= old_length);
 
        /* The reason why the instance's other_infos list can be
         * shorter than the uninstanted class's is that when we mark
@@ -743,56 +631,6 @@ fill_in_rgctx_template_slot (MonoClass *class, int index, gpointer data, int inf
         */
        g_assert (old_instances_length <= old_length);
 
-       /* For all rgctx's on this level: Instantiate the type and put
-        * the class in the rgctx.
-        */
-       if (generic_class_rgctx_hash)
-               instances = g_hash_table_lookup (generic_class_rgctx_hash, class);
-       else
-               instances = NULL;
-
-       while (instances) {
-               MonoVTable *vtable = instances->data;
-               MonoRuntimeGenericContextTemplate *instance_template;
-               int real_index;
-               gpointer *table;
-
-               instance_template = mono_class_get_runtime_generic_context_template (class_uninstantiated (vtable->klass));
-
-               g_assert (vtable->runtime_generic_context);
-
-               if (index < MONO_RGCTX_MAX_OTHER_INFOS) {
-                       real_index = index;
-                       table = vtable->runtime_generic_context->other_infos;
-               } else {
-                       real_index = index - MONO_RGCTX_MAX_OTHER_INFOS;
-
-                       if (old_instances_length == new_length) {
-                               table = vtable->runtime_generic_context->extra_other_infos;
-                       } else {
-                               g_assert (old_instances_extra_length < real_index + 1);
-
-                               /* Allocate new table with the required number
-                                  of slots and copy the old slots over. */
-                               mono_domain_lock (vtable->domain);
-                               table = mono_mempool_alloc0 (vtable->domain->mp,
-                                       sizeof (gpointer) * (real_index + 1));
-                               mono_domain_unlock (vtable->domain);
-
-                               memcpy (table, vtable->runtime_generic_context->extra_other_infos,
-                                       sizeof (gpointer) * old_instances_extra_length);
-                               mono_memory_write_barrier ();
-                               vtable->runtime_generic_context->extra_other_infos = table;
-                       }
-               }
-
-               g_assert (!table [real_index]);
-
-               //g_print ("rgctx %s . other_infos [%d] = %s\n", mono_type_get_full_name (vtable->klass), index, mono_type_get_full_name (other_class));
-
-               instances = instances->next;
-       }
-
        /* Recurse for all subclasses */
        if (generic_subclass_hash)
                subclass = g_hash_table_lookup (generic_subclass_hash, class);
@@ -800,16 +638,16 @@ fill_in_rgctx_template_slot (MonoClass *class, int index, gpointer data, int inf
                subclass = NULL;
 
        while (subclass) {
-               MonoRuntimeGenericContextOtherInfoTemplate *subclass_oti;
+               MonoRuntimeGenericContextOtherInfoTemplate subclass_oti;
                MonoRuntimeGenericContextTemplate *subclass_template = class_lookup_rgctx_template (subclass);
 
                g_assert (!subclass->generic_class);
                g_assert (subclass_template);
 
-               subclass_oti = rgctx_template_get_other_slot (class_lookup_rgctx_template (subclass->parent), index);
-               g_assert (subclass_oti->data);
+               subclass_oti = class_get_rgctx_template_oti (subclass->parent, index);
+               g_assert (subclass_oti.data);
 
-               fill_in_rgctx_template_slot (subclass, index, subclass_oti->data, info_type);
+               fill_in_rgctx_template_slot (subclass, index, subclass_oti.data, info_type);
 
                subclass = subclass_template->next_subclass;
        }
@@ -840,13 +678,15 @@ register_other_info (MonoClass *class, gpointer data, int info_type)
        parent = class->parent;
        while (parent != NULL) {
                MonoRuntimeGenericContextTemplate *parent_template;
+               MonoRuntimeGenericContextOtherInfoTemplate *oti;
 
                if (parent->generic_class)
                        parent = parent->generic_class->container_class;
 
                parent_template = mono_class_get_runtime_generic_context_template (parent);
+               oti = rgctx_template_get_other_slot (parent_template, i);
 
-               if (rgctx_template_get_other_slot (parent_template, i))
+               if (oti && oti->data)
                        break;
 
                rgctx_template_set_other_slot (parent->image, parent_template, i, MONO_RGCTX_SLOT_USED_MARKER, 0);
@@ -868,10 +708,12 @@ other_info_equal (gpointer data1, gpointer data2, int info_type)
        case MONO_RGCTX_INFO_STATIC_DATA:
        case MONO_RGCTX_INFO_KLASS:
        case MONO_RGCTX_INFO_VTABLE:
+       case MONO_RGCTX_INFO_TYPE:
        case MONO_RGCTX_INFO_REFLECTION_TYPE:
                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:
+       case MONO_RGCTX_INFO_CLASS_FIELD:
                return data1 == data2;
        default:
                g_assert_not_reached ();
@@ -893,19 +735,22 @@ int
 mono_class_lookup_or_register_other_info (MonoClass *class, gpointer data, int info_type,
        MonoGenericContext *generic_context)
 {
+       static gboolean inited = FALSE;
+       static int max_slot = 0;
+
        MonoRuntimeGenericContextTemplate *rgctx_template =
                mono_class_get_runtime_generic_context_template (class);
-       int i, num_other_infos;
+       MonoRuntimeGenericContextOtherInfoTemplate *oti;
+       int i;
+
+       g_assert (!class->generic_class && class->generic_container);
 
        templates_lock ();
 
-       num_other_infos = rgctx_template_num_other_infos (rgctx_template);
-       for (i = 0; i < num_other_infos; ++i) {
-               /* FIXME: This is quadratic in complexity! */
-               MonoRuntimeGenericContextOtherInfoTemplate *oti = rgctx_template_get_other_slot (rgctx_template, i);
+       for (oti = rgctx_template->other_infos, i = 0; oti; oti = oti->next, ++i) {
                gpointer inflated_data;
 
-               if (!oti || oti->info_type != info_type)
+               if (!oti || oti->info_type != info_type || !oti->data)
                        continue;
 
                inflated_data = inflate_other_info (oti, generic_context);
@@ -920,154 +765,113 @@ mono_class_lookup_or_register_other_info (MonoClass *class, gpointer data, int i
 
        templates_unlock ();
 
+       if (!inited) {
+               mono_counters_register ("RGCTX max slot number", MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &max_slot);
+               inited = TRUE;
+       }
+       if (i > max_slot)
+               max_slot = i;
+
+
        return i;
 }
 
-static void
-instantiate_arg_info (MonoDomain *domain, MonoRuntimeGenericArgInfo *destination, MonoType *arg_info,
-               MonoGenericContext *context)
+int
+mono_class_rgctx_get_array_size (int n)
 {
-       MonoType *arg_type;
-       MonoClass *arg_class;
-       MonoVTable *vtable;
-
-       if (!arg_info)
-               return;
-
-       arg_type = mono_class_inflate_generic_type (arg_info, context);
-
-       arg_class = mono_class_from_mono_type (arg_type);
-       g_assert (arg_class);
+       g_assert (n >= 0 && n < 30);
 
-       vtable = mono_class_vtable (domain, arg_class);
-
-       destination->static_data = vtable->data;
-       destination->klass = arg_class;
-       destination->vtable = vtable;
+       return 4 << n;
 }
 
 /*
- * LOCKING: domain lock for rgctx->vtable->domain
+ * LOCKING: domain lock
  */
-static void
-rgctx_alloc_extra_other_types (MonoRuntimeGenericContext *rgctx)
+static gpointer*
+alloc_rgctx_array (MonoDomain *domain, int n)
 {
-       MonoClass *class = rgctx->vtable->klass;
-       MonoDomain *domain = rgctx->vtable->domain;
-       MonoRuntimeGenericContextTemplate *rgctx_template;
-       int num_extra_other_infos;
+       static gboolean inited = FALSE;
+       static int num_alloced = 0;
+       static int bytes_alloced = 0;
+
+       int size = mono_class_rgctx_get_array_size (n) * sizeof (gpointer);
+       gpointer array = mono_mempool_alloc0 (domain->mp, size);
+
+       if (!inited) {
+               mono_counters_register ("RGCTX num arrays alloced", MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &num_alloced);
+               mono_counters_register ("RGCTX bytes alloced", MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &bytes_alloced);
+               inited = TRUE;
+       }
 
-       rgctx_template = mono_class_get_runtime_generic_context_template (class_uninstantiated (class));
-       num_extra_other_infos = MAX (rgctx_template_num_other_infos (rgctx_template) - MONO_RGCTX_MAX_OTHER_INFOS, 0);
+       num_alloced++;
+       bytes_alloced += size;
 
-       if (num_extra_other_infos > 0)
-               rgctx->extra_other_infos = mono_mempool_alloc0 (domain->mp,
-                       sizeof (gpointer) * num_extra_other_infos);
+       return array;
 }
 
 /*
  * mono_class_fill_runtime_generic_context:
- * @rgctx: a runtime generic context
+ * @class_vtable: a vtable
+ * @slot: a slot index to be instantiated
  *
- * Instantiates all slots of the runtime generic context rgctx.
+ * Instantiates a slot in the RGCTX.
  */
-void
-mono_class_fill_runtime_generic_context (MonoRuntimeGenericContext *rgctx)
+gpointer
+mono_class_fill_runtime_generic_context (MonoVTable *class_vtable, guint32 slot)
 {
-       MonoVTable *class_vtable = rgctx->vtable;
+       static gboolean inited = FALSE;
+       static int num_alloced = 0;
+
+       MonoRuntimeGenericContext *rgctx;
        MonoDomain *domain = class_vtable->domain;
        MonoClass *class = class_vtable->klass;
-       int depth = class->idepth;
        MonoGenericContext *context = &class->generic_class->context;
-       MonoRuntimeGenericSuperInfo *super_infos = (MonoRuntimeGenericSuperInfo*)rgctx - depth;
-       MonoRuntimeGenericContextTemplate *rgctx_template;
-       MonoRuntimeGenericContextOtherInfoTemplate *oti;
-       MonoClass *super;
-       int i;
-
-       rgctx_template = mono_class_get_runtime_generic_context_template (class_uninstantiated (class));
+       MonoRuntimeGenericContextOtherInfoTemplate oti;
+       int i, first_slot, size;
+       gpointer info;
 
        mono_domain_lock (domain);
 
-       depth = 0;
-       for (super = class; super; super = super->parent) {
-               MonoVTable *vtable = mono_class_vtable (domain, super);
-
-               super_infos [depth].static_data = vtable->data;
-               super_infos [depth].klass = super;
-               super_infos [depth].vtable = vtable;
-
-               depth++;
+       if (!inited) {
+               mono_counters_register ("RGCTX num alloced", MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &num_alloced);
+               inited = TRUE;
        }
 
-       rgctx_alloc_extra_other_types (rgctx);
-
-       for (i = 0, oti = rgctx_template->other_infos; oti; ++i, oti = oti->next) {
-               gpointer *arg_info;
-
-               if (i < MONO_RGCTX_MAX_OTHER_INFOS)
-                       arg_info = &rgctx->other_infos [i];
-               else
-                       arg_info = &rgctx->extra_other_infos [i - MONO_RGCTX_MAX_OTHER_INFOS];
-
-               *arg_info = instantiate_other_info (domain, oti, context);
+       rgctx = class_vtable->runtime_generic_context;
+       if (!rgctx) {
+               rgctx = alloc_rgctx_array (domain, 0);
+               class_vtable->runtime_generic_context = rgctx;
+               num_alloced++;
        }
 
-       for (i = 0; i < rgctx_template->num_arg_infos; ++i)
-               instantiate_arg_info (domain, &rgctx->arg_infos [i], rgctx_template->arg_infos [i], context);
-
-       mono_domain_unlock (domain);
-}
-
-/*
- * mono_class_setup_runtime_generic_context:
- * @class: a class
- * @domain: a domain
- *
- * Sets up the runtime generic context of class in domain.
- */
-void
-mono_class_setup_runtime_generic_context (MonoClass *class, MonoDomain *domain)
-{
-       MonoVTable *class_vtable = mono_class_vtable (domain, class);
-       int depth = class->idepth;
-       MonoRuntimeGenericSuperInfo *super_infos;
-       MonoRuntimeGenericContext *rgctx;
-       MonoRuntimeGenericContextTemplate *rgctx_template;
-
-       /* Never setup a rgctx for an open class. */
-       if (mono_class_check_context_used (class))
-               return;
+       /* First check whether that slot isn't already instantiated.
+          This might happen because lookup doesn't lock.  Allocate
+          arrays on the way. */
+       first_slot = 0;
+       size = mono_class_rgctx_get_array_size (0);
+       for (i = 0; ; ++i) {
+               if (slot < first_slot + size - 1) {
+                       info = rgctx [slot - first_slot + 1];
+                       if (info) {
+                               mono_domain_unlock (domain);
+                               return info;
+                       }
+                       break;
+               }
+               if (!rgctx [0])
+                       rgctx [0] = alloc_rgctx_array (domain, i + 1);
+               rgctx = rgctx [0];
+               first_slot += size - 1;
+               size = mono_class_rgctx_get_array_size (i + 1);
+       }
 
-       //g_print ("setting up rgctx for %s\n", mono_type_get_full_name (class));
+       g_assert (!rgctx [slot - first_slot + 1]);
 
-       /* We have to take the lock here and only release it after
-        * we've registered the vtable because otherwise another
-        * thread might add a slot to the template which we wouldn't
-        * know anything about and we'd end up with a rgctx that's not
-        * fully filled in.
-        */
-       templates_lock ();
+       oti = class_get_rgctx_template_oti (class_uninstantiated (class), slot);
 
-       rgctx_template = mono_class_get_runtime_generic_context_template (class_uninstantiated (class));
+       info = rgctx [slot - first_slot + 1] = instantiate_other_info (domain, &oti, context);
 
-       mono_domain_lock (domain);
-       /* We don't allocate arg_infos because we don't use it yet.
-        */
-       super_infos = mono_mempool_alloc0 (domain->mp,
-               sizeof (MonoRuntimeGenericSuperInfo) * depth +
-               sizeof (MonoRuntimeGenericContext) +
-               sizeof (MonoRuntimeGenericArgInfo) * rgctx_template->num_arg_infos);
        mono_domain_unlock (domain);
 
-       rgctx = class_vtable->runtime_generic_context = (MonoRuntimeGenericContext*) (super_infos + depth);
-
-       rgctx->domain = domain;
-       rgctx->vtable = class_vtable;
-
-       rgctx_alloc_extra_other_types (rgctx);
-
-       register_rgctx_vtable (class_vtable);
-
-       templates_unlock ();
+       return info;
 }
index adba56959e9ee21656e7345ee94d895ac2181023..e372b78fbb21584949ad96003d5d33b6b30a59c1 100644 (file)
@@ -1299,9 +1299,6 @@ mono_image_close (MonoImage *image)
        if (image->rgctx_template_hash)
                g_hash_table_destroy (image->rgctx_template_hash);
 
-       if (image->generic_class_open_instances_hash)
-               g_hash_table_destroy (image->generic_class_open_instances_hash);
-
        if (image->interface_bitset) {
                mono_unload_interface_ids (image->interface_bitset);
                mono_bitset_free (image->interface_bitset);
index 7247a8bf88cd9da9335a6d9d261a753845c10e9f..a7174733bef498af0f0eef433b85d6070d0e3af8 100644 (file)
@@ -200,13 +200,6 @@ struct _MonoImage {
        GHashTable *castclass_cache;
        GHashTable *proxy_isinst_cache;
        GHashTable *rgctx_template_hash; /* LOCKING: templates lock */
-       /* Maps from uninstantiated generic classes to GSList's of
-        * instantiated open generic classes whose container class is the key
-        * class.
-        *
-        * LOCKING: templates lock
-        */
-       GHashTable *generic_class_open_instances_hash;
 
        /*
         * indexed by token and MonoGenericContext pointer
index 0703926c6944ac101edf619928f5958d165d4fde..599480f709d224d53387f51d24526f16fec27ff5 100644 (file)
@@ -1301,21 +1301,6 @@ mono_class_vtable (MonoDomain *domain, MonoClass *class)
        return mono_class_create_runtime_vtable (domain, class);
 }
 
-static gboolean
-class_needs_rgctx (MonoClass *class)
-{
-       if (!mono_class_generic_sharing_enabled (class))
-               return FALSE;
-
-       while (class) {
-               if (class->generic_class)
-                       return TRUE;
-               class = class->parent;
-       }
-
-       return FALSE;
-}
-
 static MonoVTable *
 mono_class_create_runtime_vtable (MonoDomain *domain, MonoClass *class)
 {
@@ -1558,9 +1543,6 @@ mono_class_create_runtime_vtable (MonoDomain *domain, MonoClass *class)
                }
        }
 
-       if (class_needs_rgctx (class))
-               mono_class_setup_runtime_generic_context (class, domain);
-
        mono_domain_unlock (domain);
 
        /* Initialization is now complete, we can throw if the InheritanceDemand aren't satisfied */
index b9756c90305b756b4dce0845864003b610f6df7a..acd773a5f611180a21756433372670185cae5a3c 100644 (file)
@@ -1,3 +1,18 @@
+2008-04-28  Mark Probst  <mark.probst@gmail.com>
+
+       * mini.h, mini.c: Lots of code for accessing the old RGCTX
+       deleted.  The only way to access the new RGCTX is via the
+       trampline.
+
+       * mini.c, mini-amd64, mini-x86.c, mini-exceptions.c: Pass the
+       vtable instead of the RGCTX to static methods.
+
+       * mini-tramplines.c, tramp-amd64.c, tramp-x86.c: Trampoline for
+       accessing the new RGCTX.
+
+       * generic-sharing.c: There is no separation between self, type
+       arguments and other types in the RGCTX anymore.
+
 2008-04-25  Jonathan Chambers <joncham@gmail.com>
 
        * mini-amd64.c (add_general): Remove previous stack adjustment.
index dc1f7423675da2e97b7909665b876f06cc738cbe..fd55c59e7d97a7350946142630232427400bd6b0 100644 (file)
@@ -280,12 +280,6 @@ mono_method_get_declaring_generic_method (MonoMethod *method)
        return inflated->declaring;
 }
 
-static gboolean
-inflated_type_is_equal_to_class (MonoType *inflated_type, MonoClass *klass)
-{
-       return klass == mono_class_from_mono_type (inflated_type);
-}
-
 /*
  * mono_class_generic_class_relation:
  * @klass: the class to be investigated
@@ -306,40 +300,11 @@ int
 mono_class_generic_class_relation (MonoClass *klass, int info_type, MonoClass *method_klass,
        MonoGenericContext *generic_context, int *arg_num)
 {
-       MonoRuntimeGenericContextTemplate *rgctx_template =
-               mono_class_get_runtime_generic_context_template (method_klass);
-       int i;
-
-       /* Reflection types can only be handled in the extensible
-          rgctx part. */
-       if (info_type != MONO_RGCTX_INFO_REFLECTION_TYPE) {
-               for (i = 0; i < rgctx_template->num_arg_infos; ++i) {
-                       MonoType *arg_info = rgctx_template->arg_infos [i];
-                       MonoType *inflated_arg;
-
-                       if (arg_info == NULL)
-                               continue;
-
-                       inflated_arg = mono_class_inflate_generic_type(arg_info, generic_context);
-
-                       if (inflated_type_is_equal_to_class (inflated_arg, klass)) {
-                               if (arg_num)
-                                       *arg_num = i;
-                               return MINI_GENERIC_CLASS_RELATION_ARGUMENT;
-                       }
-               }
+       int i = mono_class_lookup_or_register_other_info (method_klass, &klass->byval_arg, info_type, generic_context);
 
-               if (!klass->generic_class && !klass->generic_container)
-                       g_assert_not_reached ();
-
-               if (mini_class_get_container_class (klass) == mini_class_get_container_class (method_klass) &&
-                               mono_generic_context_equal_deep (mini_class_get_context (klass), generic_context))
-                       return MINI_GENERIC_CLASS_RELATION_SELF;
-       }
-
-       i = mono_class_lookup_or_register_other_info (method_klass, &klass->byval_arg, info_type, generic_context);
        if (arg_num)
                *arg_num = i;
+
        return MINI_GENERIC_CLASS_RELATION_OTHER_TABLE;
 }
 
@@ -368,7 +333,7 @@ token_context_equal (MonoTokenAndContext *tc1, MonoTokenAndContext *tc2)
 /*
  * mono_helper_get_rgctx_other_ptr:
  * @caller_class: the klass of the calling method
- * @rgctx: the runtime generic context
+ * @vtable: the vtable with the runtime generic context
  * @token: the token which to look up
  * @token_source: what kind of item the token is for
  * @rgctx_type: the kind of value requested
@@ -379,16 +344,14 @@ token_context_equal (MonoTokenAndContext *tc1, MonoTokenAndContext *tc2)
  * static_data pointer).
  */
 gpointer
-mono_helper_get_rgctx_other_ptr (MonoClass *caller_class, MonoRuntimeGenericContext *rgctx,
+mono_helper_get_rgctx_other_ptr (MonoClass *caller_class, MonoVTable *vtable,
        guint32 token, guint32 token_source, guint32 rgctx_type, gint32 rgctx_index)
 {
        MonoImage *image = caller_class->image;
-       int depth = caller_class->idepth;
-       MonoRuntimeGenericSuperInfo *super_info = &((MonoRuntimeGenericSuperInfo*)rgctx)[-depth];
-       MonoClass *klass = super_info->klass;
+       MonoClass *klass = vtable->klass;
        MonoClass *result = NULL;
        MonoTokenAndContext tc = { token, &klass->generic_class->context };
-       gpointer rgctx_result_ptr, result_ptr;
+       gpointer result_ptr;
 
        mono_loader_lock ();
 
@@ -455,28 +418,17 @@ mono_helper_get_rgctx_other_ptr (MonoClass *caller_class, MonoRuntimeGenericCont
                result_ptr = result;
                break;
        case MONO_RGCTX_INFO_STATIC_DATA: {
-               MonoVTable *vtable = mono_class_vtable (rgctx->domain, result);
-               result_ptr = vtable->data;
+               MonoVTable *result_vtable = mono_class_vtable (vtable->domain, result);
+               result_ptr = result_vtable->data;
                break;
        }
        case MONO_RGCTX_INFO_VTABLE:
-               result_ptr = mono_class_vtable (rgctx->domain, result);
+               result_ptr = mono_class_vtable (vtable->domain, result);
                break;
        default:
                g_assert_not_reached ();
        }
 
-       g_assert (rgctx_index >= 0);
-       if (rgctx_index < MONO_RGCTX_MAX_OTHER_INFOS) {
-               rgctx_result_ptr = rgctx->other_infos [rgctx_index];
-       } else {
-               g_assert (rgctx->extra_other_infos);
-
-               rgctx_result_ptr = rgctx->extra_other_infos [rgctx_index - MONO_RGCTX_MAX_OTHER_INFOS];
-       }
-
-       g_assert (rgctx_result_ptr == result);
-
        return result_ptr;
 }
 
index 3e9c407d66ed3dcf45d18fc37e93534e3a45574b..de3fd7737303625deaa8cf24a8071f0af00f131c 100644 (file)
@@ -5317,10 +5317,10 @@ mono_arch_find_this_argument (gpointer *regs, MonoMethod *method, MonoGenericSha
 }
 #endif
 
-MonoRuntimeGenericContext*
-mono_arch_find_static_call_rgctx (gpointer *regs, guint8 *code)
+MonoVTable*
+mono_arch_find_static_call_vtable (gpointer *regs, guint8 *code)
 {
-       return (MonoRuntimeGenericContext*) regs [MONO_ARCH_RGCTX_REG];
+       return (MonoVTable*) regs [MONO_ARCH_RGCTX_REG];
 }
 
 MonoInst*
index e76fc87109d64737cf55c6b11e6354ca68ba0244..75cf10a4956de13fa3393a6290e1138faa4af953 100644 (file)
@@ -620,9 +620,9 @@ get_exception_catch_class (MonoJitExceptionInfo *ei, MonoJitInfo *ji, MonoContex
                                        gi->this_offset);
 
                if (ji->method->flags & METHOD_ATTRIBUTE_STATIC) {
-                       MonoRuntimeGenericContext *rgctx = info;
+                       MonoVTable *vtable = info;
 
-                       class = rgctx->vtable->klass;
+                       class = vtable->klass;
                } else {
                        MonoObject *this = info;
 
index 4d34e42282d18d50381abc17109da0972309936a..174805ad279fd745535e26eb4b9eee80bb7da0a2 100644 (file)
@@ -6,6 +6,7 @@
 #include <mono/metadata/metadata-internals.h>
 #include <mono/metadata/marshal.h>
 #include <mono/metadata/tabledefs.h>
+#include <mono/utils/mono-counters.h>
 
 #ifdef HAVE_VALGRIND_MEMCHECK_H
 #include <valgrind/memcheck.h>
@@ -170,9 +171,9 @@ mono_magic_trampoline (gssize *regs, guint8 *code, MonoMethod *m, guint8* tramp)
 
                if (m->flags & METHOD_ATTRIBUTE_STATIC) {
 #ifdef MONO_ARCH_RGCTX_REG
-                       MonoRuntimeGenericContext *rgctx = mono_arch_find_static_call_rgctx ((gpointer*)regs, code);
+                       MonoVTable *vtable = mono_arch_find_static_call_vtable ((gpointer*)regs, code);
 
-                       klass = rgctx->vtable->klass;
+                       klass = vtable->klass;
 #else
                        g_assert_not_reached ();
 #endif
@@ -405,29 +406,21 @@ mono_generic_class_init_trampoline (gssize *regs, guint8 *code, MonoVTable *vtab
 }
 
 static gpointer
-mono_rgctx_lazy_fetch_trampoline (gssize *regs, guint8 *code, MonoRuntimeGenericContext *rgctx, guint8 *tramp)
+mono_rgctx_lazy_fetch_trampoline (gssize *regs, guint8 *code, MonoVTable *vtable, guint8 *tramp)
 {
-       guint32 encoded_offset = mono_arch_get_rgctx_lazy_fetch_offset ((gpointer*)regs);
-       gpointer result;
+       static gboolean inited = FALSE;
+       static int num_lookups = 0;
 
-       mono_class_fill_runtime_generic_context (rgctx);
+       guint32 slot = mono_arch_get_rgctx_lazy_fetch_offset ((gpointer*)regs);
 
-       if (MONO_RGCTX_OFFSET_IS_INDIRECT (encoded_offset)) {
-               int indirect_slot = MONO_RGCTX_OFFSET_INDIRECT_SLOT (encoded_offset);
-               int offset = MONO_RGCTX_OFFSET_INDIRECT_OFFSET (encoded_offset);
-
-               g_assert (indirect_slot == 0);
-               
-               result = *(gpointer*)((guint8*)rgctx->extra_other_infos + offset);
-       } else {
-               int offset = MONO_RGCTX_OFFSET_DIRECT_OFFSET (encoded_offset);
-
-               result = *(gpointer*)((guint8*)rgctx + offset);
+       if (!inited) {
+               mono_counters_register ("RGCTX unmanaged lookups", MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &num_lookups);
+               inited = TRUE;
        }
 
-       g_assert (result);
+       num_lookups++;
 
-       return result;
+       return mono_class_fill_runtime_generic_context (vtable, slot);
 }
 
 #ifdef MONO_ARCH_HAVE_CREATE_DELEGATE_TRAMPOLINE
index 2bd40b0cd51bb1a3fba30541c8cfec95bb0d4a03..b2c1eb58ef85ec39358938a96b579fc4e65a4825 100644 (file)
@@ -4191,10 +4191,10 @@ mono_arch_find_this_argument (gpointer *regs, MonoMethod *method, MonoGenericSha
 }
 #endif
 
-MonoRuntimeGenericContext*
-mono_arch_find_static_call_rgctx (gpointer *regs, guint8 *code)
+MonoVTable*
+mono_arch_find_static_call_vtable (gpointer *regs, guint8 *code)
 {
-       return (MonoRuntimeGenericContext*) regs [MONO_ARCH_RGCTX_REG];
+       return (MonoVTable*) regs [MONO_ARCH_RGCTX_REG];
 }
 
 MonoInst*
index d03501b7c4d02c30eb120c5de6a003df7e56eaf4..31452a2d4ab23b44f64d7f067edbd46785378d89 100644 (file)
                if (method->klass->valuetype)   \
                        GENERIC_SHARING_FAILURE ((opcode)); \
        } while (0)
+#define GET_RGCTX(rgctx) do {                                          \
+               MonoInst *this = NULL;                                  \
+               GENERIC_SHARING_FAILURE_IF_VALUETYPE_METHOD(*ip);       \
+               if (!(method->flags & METHOD_ATTRIBUTE_STATIC))         \
+                       NEW_ARGLOAD (cfg, this, 0);                     \
+               (rgctx) = get_runtime_generic_context (cfg, method, this, ip); \
+       } while (0)
 
 #define MONO_CHECK_THIS(ins) (mono_method_signature (cfg->method)->hasthis && (ins)->ssa_op == MONO_SSA_LOAD && (ins)->inst_left->inst_c0 == 0)
 
@@ -1807,7 +1814,7 @@ mono_get_got_var (MonoCompile *cfg)
 }
 
 static MonoInst *
-mono_get_rgctx_var (MonoCompile *cfg)
+mono_get_vtable_var (MonoCompile *cfg)
 {
        g_assert (cfg->generic_sharing_context);
 
@@ -4380,55 +4387,36 @@ set_exception_type_from_invalid_il (MonoCompile *cfg, MonoMethod *method, unsign
        g_free (method_code);
 }
 
-/*
- * Generates this->vtable->runtime_generic_context
- */
-static MonoInst*
-get_runtime_generic_context_from_this (MonoCompile *cfg, MonoInst *this, unsigned char *ip)
-{
-       MonoInst *vtable, *rgc_ptr_addr, *rgc_ptr_offset, *rgc_ptr;
-
-       MONO_INST_NEW (cfg, vtable, CEE_LDIND_I);
-       vtable->cil_code = ip;
-       vtable->inst_left = this;
-       vtable->type = STACK_PTR;
-
-       NEW_ICONST (cfg, rgc_ptr_offset, G_STRUCT_OFFSET (MonoVTable, runtime_generic_context));
-
-       MONO_INST_NEW (cfg, rgc_ptr_addr, OP_PADD);
-       rgc_ptr_addr->cil_code = ip;
-       rgc_ptr_addr->inst_left = vtable;
-       rgc_ptr_addr->inst_right = rgc_ptr_offset;
-       rgc_ptr_addr->type = STACK_PTR;
-
-       MONO_INST_NEW (cfg, rgc_ptr, CEE_LDIND_I);
-       rgc_ptr->cil_code = ip;
-       rgc_ptr->inst_left = rgc_ptr_addr;
-       rgc_ptr->type = STACK_PTR;
-
-       return rgc_ptr;
-}
-
 static MonoInst*
 get_runtime_generic_context (MonoCompile *cfg, MonoMethod *method, MonoInst *this, unsigned char *ip)
 {
        g_assert (!method->klass->valuetype);
 
        if (method->flags & METHOD_ATTRIBUTE_STATIC) {
-               MonoInst *rgctx_loc, *rgctx_var;
+               MonoInst *vtable_loc, *vtable_var;
 
-               rgctx_loc = mono_get_rgctx_var (cfg);
-               NEW_TEMPLOAD (cfg, rgctx_var, rgctx_loc->inst_c0);
+               vtable_loc = mono_get_vtable_var (cfg);
+               NEW_TEMPLOAD (cfg, vtable_var, vtable_loc->inst_c0);
 
-               return rgctx_var;
+               return vtable_var;
        } else {
-               return get_runtime_generic_context_from_this (cfg, this, ip);
+               MonoInst *vtable;
+
+               MONO_INST_NEW (cfg, vtable, CEE_LDIND_I);
+               vtable->cil_code = ip;
+               vtable->inst_left = this;
+               vtable->type = STACK_PTR;
+
+               return vtable;
        }
 }
 
 static gpointer
 create_rgctx_lazy_fetch_trampoline (guint32 offset)
 {
+       static gboolean inited = FALSE;
+       static int num_trampolines = 0;
+
        gpointer tramp, ptr;
 
        mono_jit_lock ();
@@ -4449,106 +4437,14 @@ create_rgctx_lazy_fetch_trampoline (guint32 offset)
        g_hash_table_insert (rgctx_lazy_fetch_trampoline_hash, GUINT_TO_POINTER (offset), ptr);
        mono_jit_unlock ();
 
-       return ptr;
-}      
-
-static MonoInst*
-lazy_fetch_rgctx_direct_field (MonoCompile *cfg, MonoBasicBlock *bblock, MonoInst *rgc_ptr, int offset, unsigned char *ip)
-{
-       MonoMethodSignature *sig = helper_sig_rgctx_lazy_fetch_trampoline;
-       guint8 *tramp = create_rgctx_lazy_fetch_trampoline (MONO_RGCTX_ENCODE_DIRECT_OFFSET (offset));
-       int temp;
-       MonoInst *field;
-
-       temp = mono_emit_native_call (cfg, bblock, tramp, sig, &rgc_ptr, ip, FALSE, FALSE); 
-
-       NEW_TEMPLOAD (cfg, field, temp);
-
-       return field;
-}
-
-static MonoInst*
-lazy_fetch_rgctx_indirect_field (MonoCompile *cfg, MonoBasicBlock *bblock, MonoInst *rgc_ptr, int offset, unsigned char *ip)
-{
-       MonoMethodSignature *sig = helper_sig_rgctx_lazy_fetch_trampoline;
-       guint8 *tramp = create_rgctx_lazy_fetch_trampoline (MONO_RGCTX_ENCODE_INDIRECT_OFFSET (offset));
-       int temp;
-       MonoInst *field;
-
-       temp = mono_emit_native_call (cfg, bblock, tramp, sig, &rgc_ptr, ip, FALSE, FALSE); 
-
-       NEW_TEMPLOAD (cfg, field, temp);
-
-       return field;
-}
-
-/*
- * Generates ((MonoRuntimeGenericSuperInfo*)rgc)[-depth].XXX where XXX
- * is specified by rgctx_type.
- */
-static MonoInst*
-get_runtime_generic_context_super_ptr (MonoCompile *cfg, MonoBasicBlock *bblock,
-       MonoInst *rgc_ptr, int depth, int rgctx_type, unsigned char *ip)
-{
-       int field_offset_const, offset;
-
-       g_assert (depth >= 1);
-
-       switch (rgctx_type) {
-       case MONO_RGCTX_INFO_STATIC_DATA :
-               field_offset_const = G_STRUCT_OFFSET (MonoRuntimeGenericSuperInfo, static_data);
-               break;
-       case MONO_RGCTX_INFO_KLASS :
-               field_offset_const = G_STRUCT_OFFSET (MonoRuntimeGenericSuperInfo, klass);
-               break;
-       case MONO_RGCTX_INFO_VTABLE:
-               field_offset_const = G_STRUCT_OFFSET (MonoRuntimeGenericSuperInfo, vtable);
-               break;
-       default :
-               g_assert_not_reached ();
+       if (!inited) {
+               mono_counters_register ("RGCTX num lazy fetch trampolines",
+                               MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &num_trampolines);
+               inited = TRUE;
        }
+       num_trampolines++;
 
-       offset = -depth * sizeof (MonoRuntimeGenericSuperInfo) + field_offset_const;
-
-       return lazy_fetch_rgctx_direct_field (cfg, bblock, rgc_ptr, offset, ip);
-}
-
-static int
-get_rgctx_arg_info_field_offset (int rgctx_type)
-{
-       switch (rgctx_type) {
-       case MONO_RGCTX_INFO_STATIC_DATA :
-               return G_STRUCT_OFFSET (MonoRuntimeGenericArgInfo, static_data);
-       case MONO_RGCTX_INFO_KLASS:
-               return G_STRUCT_OFFSET (MonoRuntimeGenericArgInfo, klass);
-       case MONO_RGCTX_INFO_VTABLE :
-               return G_STRUCT_OFFSET (MonoRuntimeGenericArgInfo, vtable);
-       default:
-               g_assert_not_reached ();
-       }
-}
-
-/*
- * Generates rgc->arg_infos [arg_num].XXX where XXX is specified by
- * rgctx_type;
- */
-static MonoInst*
-get_runtime_generic_context_arg_ptr (MonoCompile *cfg, MonoBasicBlock *bblock,
-       MonoInst *rgc_ptr, int arg_num, int rgctx_type, unsigned char *ip)
-{
-       int arg_info_offset, arg_info_field_offset, offset;
-
-       g_assert (arg_num >= 0);
-       //g_assert (!lazy);
-
-       arg_info_offset = G_STRUCT_OFFSET (MonoRuntimeGenericContext, arg_infos) +
-               arg_num * sizeof (MonoRuntimeGenericArgInfo);
-
-       arg_info_field_offset = get_rgctx_arg_info_field_offset (rgctx_type);
-
-       offset = arg_info_offset + arg_info_field_offset;
-
-       return lazy_fetch_rgctx_direct_field (cfg, bblock, rgc_ptr, offset, ip);
+       return ptr;
 }
 
 /*
@@ -4558,22 +4454,18 @@ get_runtime_generic_context_arg_ptr (MonoCompile *cfg, MonoBasicBlock *bblock,
  */
 static MonoInst*
 get_runtime_generic_context_other_table_ptr (MonoCompile *cfg, MonoBasicBlock *bblock,
-       MonoInst *rgc_ptr, int index, unsigned char *ip)
+       MonoInst *rgc_ptr, int slot, const unsigned char *ip)
 {
-       if (index < MONO_RGCTX_MAX_OTHER_INFOS) {
-               int other_type_offset;
-
-               other_type_offset = G_STRUCT_OFFSET (MonoRuntimeGenericContext, other_infos) +
-                       index * sizeof (gpointer);
+       MonoMethodSignature *sig = helper_sig_rgctx_lazy_fetch_trampoline;
+       guint8 *tramp = create_rgctx_lazy_fetch_trampoline (slot);
+       int temp;
+       MonoInst *field;
 
-               return lazy_fetch_rgctx_direct_field (cfg, bblock, rgc_ptr, other_type_offset, ip);
-       } else {
-               int slot_offset;
+       temp = mono_emit_native_call (cfg, bblock, tramp, sig, &rgc_ptr, ip, FALSE, FALSE);
 
-               slot_offset = (index - MONO_RGCTX_MAX_OTHER_INFOS) * sizeof (gpointer);
+       NEW_TEMPLOAD (cfg, field, temp);
 
-               return lazy_fetch_rgctx_indirect_field (cfg, bblock, rgc_ptr, slot_offset, ip);
-       }
+       return field;
 }
 
 static MonoInst*
@@ -4608,12 +4500,6 @@ get_runtime_generic_context_ptr (MonoCompile *cfg, MonoMethod *method, MonoBasic
        int relation = mono_class_generic_class_relation (klass, rgctx_type, method->klass, generic_context, &arg_num);
 
        switch (relation) {
-       case MINI_GENERIC_CLASS_RELATION_SELF: {
-               int depth = klass->idepth;
-               return get_runtime_generic_context_super_ptr (cfg, bblock, rgctx, depth, rgctx_type, ip);
-       }
-       case MINI_GENERIC_CLASS_RELATION_ARGUMENT:
-               return get_runtime_generic_context_arg_ptr (cfg, bblock, rgctx, arg_num, rgctx_type, ip);
        case MINI_GENERIC_CLASS_RELATION_OTHER_TABLE:
                return get_runtime_generic_context_other_table_ptr (cfg, bblock, rgctx, arg_num, ip);
        case MINI_GENERIC_CLASS_RELATION_OTHER:
@@ -4627,7 +4513,7 @@ get_runtime_generic_context_ptr (MonoCompile *cfg, MonoMethod *method, MonoBasic
 
 static MonoInst*
 get_runtime_generic_context_method (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *bblock,
-       MonoMethod *cmethod, MonoGenericContext *generic_context, MonoInst *rgctx, int rgctx_type, unsigned char *ip)
+       MonoMethod *cmethod, MonoGenericContext *generic_context, MonoInst *rgctx, int rgctx_type, const unsigned char *ip)
 {
        int arg_num = mono_class_lookup_or_register_other_info (method->klass, cmethod, rgctx_type, generic_context);
 
@@ -4895,7 +4781,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                 * (for non-static methods) are live.
                                 */
                                if (method->flags & METHOD_ATTRIBUTE_STATIC) {
-                                       mono_get_rgctx_var (cfg);
+                                       mono_get_vtable_var (cfg);
                                } else {
                                        MonoInst *this, *dummy_use;
                                        MonoType *this_type;
@@ -5471,10 +5357,10 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                        MonoMethodSignature *fsig = NULL;
                        int temp, array_rank = 0;
                        int virtual = *ip == CEE_CALLVIRT;
-                       MonoInst *rgctx_arg = NULL;
                        gboolean no_spill;
                        int context_used = 0;
-                       gboolean pass_rgctx = FALSE;
+                       gboolean pass_vtable = FALSE;
+                       MonoInst *vtable_arg = NULL;
 
                        CHECK_OPSIZE (5);
                        token = read32 (ip + 1);
@@ -5607,7 +5493,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                gboolean context_sharable = mono_generic_context_is_sharable (context, TRUE);
 
                                /*
-                                * Pass rgctx iff target method might
+                                * Pass vtable iff target method might
                                 * be shared, which means that sharing
                                 * is enabled for its class and its
                                 * context is sharable (and it's not a
@@ -5615,7 +5501,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                 */
                                if (sharing_enabled && context_sharable &&
                                                !mini_method_get_context (cmethod)->method_inst)
-                                       pass_rgctx = TRUE;
+                                       pass_vtable = TRUE;
                        }
 
                        if (cfg->generic_sharing_context && cmethod) {
@@ -5633,35 +5519,18 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                }
                        }
 
-                       if (pass_rgctx) {
+                       if (pass_vtable) {
                                if (context_used) {
-                                       MonoInst *this = NULL, *rgctx, *vtable, *field_offset, *field_addr;
-
-                                       GENERIC_SHARING_FAILURE_IF_VALUETYPE_METHOD (*ip);
+                                       MonoInst *rgctx;
 
-                                       if (!(method->flags & METHOD_ATTRIBUTE_STATIC))
-                                               NEW_ARGLOAD (cfg, this, 0);
-                                       rgctx = get_runtime_generic_context (cfg, method, this, ip);
-                                       vtable = get_runtime_generic_context_ptr (cfg, method, bblock, cmethod->klass,
+                                       GET_RGCTX (rgctx);
+                                       vtable_arg = get_runtime_generic_context_ptr (cfg, method, bblock, cmethod->klass,
                                                token, MINI_TOKEN_SOURCE_METHOD, generic_context,
                                                rgctx, MONO_RGCTX_INFO_VTABLE, ip);
-
-                                       NEW_ICONST (cfg, field_offset, G_STRUCT_OFFSET (MonoVTable, runtime_generic_context));
-
-                                       MONO_INST_NEW (cfg, field_addr, OP_PADD);
-                                       field_addr->cil_code = ip;
-                                       field_addr->inst_left = vtable;
-                                       field_addr->inst_right = field_offset;
-                                       field_addr->type = STACK_PTR;
-
-                                       MONO_INST_NEW (cfg, rgctx_arg, CEE_LDIND_I);
-                                       rgctx_arg->cil_code = ip;
-                                       rgctx_arg->inst_left = field_addr;
-                                       rgctx_arg->type = STACK_PTR;
                                } else {
                                        MonoVTable *vtable = mono_class_vtable (cfg->domain, cmethod->klass);
 
-                                       NEW_PCONST (cfg, rgctx_arg, vtable->runtime_generic_context);
+                                       NEW_VTABLECONST (cfg, vtable_arg, vtable);
                                }
                        }
 
@@ -5819,7 +5688,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
 
                        /* tail recursion elimination */
                        if ((cfg->opt & MONO_OPT_TAILC) && *ip == CEE_CALL && cmethod == method && ip [5] == CEE_RET &&
-                                       !rgctx_arg) {
+                                       !vtable_arg) {
                                gboolean has_vtargs = FALSE;
                                int i;
                                
@@ -5898,17 +5767,17 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                if (*ip == CEE_CALL)
                                        g_assert (context_used);
                                else if (*ip == CEE_CALLI)
-                                       g_assert (!rgctx_arg);
+                                       g_assert (!vtable_arg);
                                else
                                        g_assert_not_reached ();
 
                                /* Prevent inlining of methods with indirect calls */
                                INLINE_FAILURE;
                                if (no_spill) {
-                                       ins = (MonoInst*)mono_emit_rgctx_calli (cfg, bblock, fsig, sp, addr, rgctx_arg, ip);
+                                       ins = (MonoInst*)mono_emit_rgctx_calli (cfg, bblock, fsig, sp, addr, vtable_arg, ip);
                                        *sp++ = ins;                                    
                                } else {
-                                       temp = mono_emit_rgctx_calli_spilled (cfg, bblock, fsig, sp, addr, rgctx_arg, ip);
+                                       temp = mono_emit_rgctx_calli_spilled (cfg, bblock, fsig, sp, addr, vtable_arg, ip);
                                        if (temp != -1) {
                                                NEW_TEMPLOAD (cfg, *sp, temp);
                                                sp++;
@@ -5995,10 +5864,12 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                                sp++;
                                        }
                                } else if (no_spill) {
-                                       ins = (MonoInst*)mono_emit_rgctx_method_call (cfg, bblock, cmethod, fsig, sp, rgctx_arg, ip, virtual ? sp [0] : NULL);
+                                       ins = (MonoInst*)mono_emit_rgctx_method_call (cfg, bblock, cmethod, fsig, sp,
+                                                       vtable_arg, ip, virtual ? sp [0] : NULL);
                                        *sp++ = ins;
                                } else {
-                                       if ((temp = mono_emit_rgctx_method_call_spilled (cfg, bblock, cmethod, fsig, sp, rgctx_arg, ip, virtual ? sp [0] : NULL)) != -1) {
+                                       if ((temp = mono_emit_rgctx_method_call_spilled (cfg, bblock, cmethod, fsig, sp,
+                                                       vtable_arg, ip, virtual ? sp [0] : NULL)) != -1) {
                                                MonoInst *load;
                                                NEW_TEMPLOAD (cfg, load, temp);
 
@@ -7442,26 +7313,17 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                if (mono_class_needs_cctor_run (klass, method)) {
                                        MonoMethodSignature *sig = helper_sig_generic_class_init_trampoline;
                                        MonoCallInst *call;
-                                       MonoInst *vtable;
+                                       MonoInst *vtable, *rgctx;
 
                                        if (!(method->flags & METHOD_ATTRIBUTE_STATIC))
                                                NEW_ARGLOAD (cfg, this, 0);
                                        else
                                                this = NULL;
 
-                                       if (relation == MINI_GENERIC_CLASS_RELATION_SELF && this) {
-                                               MONO_INST_NEW (cfg, vtable, CEE_LDIND_I);
-                                               vtable->cil_code = ip;
-                                               vtable->inst_left = this;
-                                               vtable->type = STACK_PTR;
-                                               vtable->klass = klass;
-                                       } else {
-                                               MonoInst *rgctx = get_runtime_generic_context (cfg, method, this, ip);
-
-                                               vtable = get_runtime_generic_context_ptr (cfg, method, bblock, klass,
+                                       rgctx = get_runtime_generic_context (cfg, method, this, ip);
+                                       vtable = get_runtime_generic_context_ptr (cfg, method, bblock, klass,
                                                        token, MINI_TOKEN_SOURCE_FIELD, generic_context,
                                                        rgctx, MONO_RGCTX_INFO_VTABLE, ip);
-                                       }
 
                                        call = mono_emit_call_args (cfg, bblock, sig, NULL, FALSE, FALSE, ip, FALSE);
                                        call->inst.opcode = OP_TRAMPCALL_VTABLE;
index ba61ec02378de608a7dbe899ff1d3e4d3bd19113..1cf67903d7cec31e772ae347c4c277daa94ede9b 100644 (file)
@@ -1041,8 +1041,6 @@ enum {
 };
 
 enum {
-       MINI_GENERIC_CLASS_RELATION_SELF,
-       MINI_GENERIC_CLASS_RELATION_ARGUMENT,
        MINI_GENERIC_CLASS_RELATION_OTHER_TABLE,
        MINI_GENERIC_CLASS_RELATION_OTHER
 };
@@ -1209,7 +1207,7 @@ guchar*   mono_arch_create_trampoline_code      (MonoTrampolineType tramp_type)
 gpointer  mono_arch_create_jit_trampoline       (MonoMethod *method) MONO_INTERNAL;
 MonoJitInfo *mono_arch_create_jump_trampoline      (MonoMethod *method) MONO_INTERNAL;
 gpointer  mono_arch_create_class_init_trampoline(MonoVTable *vtable) MONO_INTERNAL;
-gpointer  mono_arch_create_rgctx_lazy_fetch_trampoline (guint32 encoded_offset) MONO_INTERNAL;
+gpointer  mono_arch_create_rgctx_lazy_fetch_trampoline (guint32 slot) MONO_INTERNAL;
 guint32          mono_arch_get_rgctx_lazy_fetch_offset (gpointer *regs) MONO_INTERNAL;
 GList    *mono_arch_get_allocatable_int_vars    (MonoCompile *cfg) MONO_INTERNAL;
 GList    *mono_arch_get_global_int_regs         (MonoCompile *cfg) MONO_INTERNAL;
@@ -1274,7 +1272,7 @@ gpointer mono_arch_get_delegate_invoke_impl     (MonoMethodSignature *sig, gbool
 gpointer mono_arch_create_specific_trampoline   (gpointer arg1, MonoTrampolineType tramp_type, MonoDomain *domain, guint32 *code_len) MONO_INTERNAL;
 void        mono_arch_emit_imt_argument         (MonoCompile *cfg, MonoCallInst *call) MONO_INTERNAL;
 MonoMethod* mono_arch_find_imt_method           (gpointer *regs, guint8 *code) MONO_INTERNAL;
-MonoRuntimeGenericContext* mono_arch_find_static_call_rgctx (gpointer *regs, guint8 *code) MONO_INTERNAL;
+MonoVTable* mono_arch_find_static_call_vtable (gpointer *regs, guint8 *code) MONO_INTERNAL;
 gpointer    mono_arch_build_imt_thunk           (MonoVTable *vtable, MonoDomain *domain, MonoIMTCheckItem **imt_entries, int count) MONO_INTERNAL;
 void    mono_arch_notify_pending_exc (void) MONO_INTERNAL;
 
@@ -1373,7 +1371,7 @@ MonoMethod* mono_method_get_declaring_generic_method (MonoMethod *method) MONO_I
 int mono_class_generic_class_relation (MonoClass *klass, int info_type, MonoClass *method_klass,
                                       MonoGenericContext *generic_context, int *arg_num) MONO_INTERNAL;
 
-gpointer mono_helper_get_rgctx_other_ptr (MonoClass *caller_class, MonoRuntimeGenericContext *rgctx,
+gpointer mono_helper_get_rgctx_other_ptr (MonoClass *caller_class, MonoVTable *vtable,
                                          guint32 token, guint32 token_source, guint32 rgctx_type,
                                          gint32 rgctx_index) MONO_INTERNAL;
 
index f9d5a318c8da60c5f6f11169ad93b8d8518f7924..6bbe437a28107371b71cd37a78cf436e66d89e6b 100644 (file)
@@ -467,55 +467,75 @@ mono_arch_create_specific_trampoline (gpointer arg1, MonoTrampolineType tramp_ty
 }      
 
 gpointer
-mono_arch_create_rgctx_lazy_fetch_trampoline (guint32 encoded_offset)
+mono_arch_create_rgctx_lazy_fetch_trampoline (guint32 slot)
 {
        guint8 *tramp = mono_get_trampoline_code (MONO_TRAMPOLINE_RGCTX_LAZY_FETCH);
-       gboolean indirect = MONO_RGCTX_OFFSET_IS_INDIRECT (encoded_offset);
-       int offset = indirect ? MONO_RGCTX_OFFSET_INDIRECT_OFFSET (encoded_offset) :
-               MONO_RGCTX_OFFSET_DIRECT_OFFSET (encoded_offset);
-       guint8 *code, *buf, *jump;
-       guint8 *dummy;
-       int slots_reg;
+       guint8 *code, *buf;
+       guint8 **rgctx_null_jumps;
+       int tramp_size;
+       int depth, index;
+       int i;
 
        g_assert (tramp);
-       if (indirect)
-               g_assert (MONO_RGCTX_OFFSET_INDIRECT_SLOT (encoded_offset) == 0);
 
-       code = buf = mono_global_codeman_reserve (32);
+       index = slot;
+       for (depth = 0; ; ++depth) {
+               int size = mono_class_rgctx_get_array_size (depth);
 
-       /* load slots ptr */
-       if (indirect) {
-               /* if indirect, load extra_other_infos ptr */
-               amd64_mov_reg_membase (buf, AMD64_RAX, AMD64_ARG_REG1, G_STRUCT_OFFSET (MonoRuntimeGenericContext, extra_other_infos), 8);
-               slots_reg = AMD64_RAX;
-       } else {
-               slots_reg = AMD64_ARG_REG1;
+               if (index < size - 1)
+                       break;
+               index -= size - 1;
        }
-       /* fetch slot */
-       amd64_mov_reg_membase (buf, AMD64_RAX, slots_reg, offset, 8);
 
-       dummy = buf;
+       tramp_size = 32 + 8 * depth;
+
+       code = buf = mono_global_codeman_reserve (tramp_size);
 
-       /* is slot null? */
+       rgctx_null_jumps = g_malloc (sizeof (guint8*) * (depth + 2));
+
+       /* load rgctx ptr from vtable */
+       amd64_mov_reg_membase (buf, AMD64_RAX, AMD64_ARG_REG1, G_STRUCT_OFFSET (MonoVTable, runtime_generic_context), 8);
+       /* is the rgctx ptr null? */
        amd64_test_reg_reg (buf, AMD64_RAX, AMD64_RAX);
-       jump = buf;
        /* if yes, jump to actual trampoline */
+       rgctx_null_jumps [0] = buf;
        amd64_branch8 (buf, X86_CC_Z, -1, 1);
 
-       /* if no, just return */
+       for (i = 0; i < depth; ++i) {
+               /* load ptr to next array */
+               amd64_mov_reg_membase (buf, AMD64_RAX, AMD64_RAX, 0, 8);
+               /* is the ptr null? */
+               amd64_test_reg_reg (buf, AMD64_RAX, AMD64_RAX);
+               /* if yes, jump to actual trampoline */
+               rgctx_null_jumps [i + 1] = buf;
+               amd64_branch8 (buf, X86_CC_Z, -1, 1);
+       }
+
+       /* fetch slot */
+       amd64_mov_reg_membase (buf, AMD64_RAX, AMD64_RAX, sizeof (gpointer) * (index + 1), 8);
+       /* is the slot null? */
+       amd64_test_reg_reg (buf, AMD64_RAX, AMD64_RAX);
+       /* if yes, jump to actual trampoline */
+       rgctx_null_jumps [depth + 1] = buf;
+       amd64_branch8 (buf, X86_CC_Z, -1, 1);
+       /* otherwise return */
        amd64_ret (buf);
 
-       x86_patch (jump, buf);
+       for (i = 0; i <= depth + 1; ++i)
+               x86_patch (rgctx_null_jumps [i], buf);
+
+       g_free (rgctx_null_jumps);
+
        /* move the rgctx pointer to the VTABLE register */
        amd64_mov_reg_reg (buf, MONO_ARCH_VTABLE_REG, AMD64_ARG_REG1, 8);
-       /* store the offset in RAX */
-       amd64_mov_reg_imm (buf, AMD64_RAX, encoded_offset);
+       /* store the slot in RAX */
+       amd64_mov_reg_imm (buf, AMD64_RAX, slot);
        /* jump to the actual trampoline */
        amd64_jump_code (buf, tramp);
 
        mono_arch_flush_icache (code, buf - code);
 
-       g_assert (buf - code <= 32);
+       g_assert (buf - code <= tramp_size);
 
        return code;
 }
index 6900d0c5e7dfbf468e18e74e5d79c5ccfdab9b52..fb9039b05789935545975defa1b9221ef1cf1c68 100644 (file)
@@ -434,76 +434,101 @@ mono_arch_create_specific_trampoline (gpointer arg1, MonoTrampolineType tramp_ty
 }
 
 gpointer
-mono_arch_create_rgctx_lazy_fetch_trampoline (guint32 encoded_offset)
+mono_arch_create_rgctx_lazy_fetch_trampoline (guint32 slot)
 {
        guint8 *tramp = mono_get_trampoline_code (MONO_TRAMPOLINE_RGCTX_LAZY_FETCH);
-       gboolean indirect = MONO_RGCTX_OFFSET_IS_INDIRECT (encoded_offset);
-       int offset = indirect ? MONO_RGCTX_OFFSET_INDIRECT_OFFSET (encoded_offset) :
-               MONO_RGCTX_OFFSET_DIRECT_OFFSET (encoded_offset);
-       guint8 *code, *buf, *jump;
-       guint8 *dummy;
+       guint8 *code, *buf;
+       guint8 **rgctx_null_jumps;
+       int tramp_size;
+       int depth, index;
+       int i;
 
        g_assert (tramp);
-       if (indirect)
-               g_assert (MONO_RGCTX_OFFSET_INDIRECT_SLOT (encoded_offset) == 0);
 
-       code = buf = mono_global_codeman_reserve (32);
+       index = slot;
+       for (depth = 0; ; ++depth) {
+               int size = mono_class_rgctx_get_array_size (depth);
 
-       /* load rgctx ptr */
-       x86_mov_reg_membase (buf, X86_EAX, X86_ESP, 4, 4);
-       if (indirect) {
-               /* if indirect, load extra_other_infos ptr */
-               x86_mov_reg_membase (buf, X86_EAX, X86_EAX, G_STRUCT_OFFSET (MonoRuntimeGenericContext, extra_other_infos), 4);
+               if (index < size - 1)
+                       break;
+               index -= size - 1;
        }
-       /* fetch slot */
-       x86_mov_reg_membase (buf, X86_EAX, X86_EAX, offset, 4);
 
-       dummy = buf;
+       tramp_size = 36 + 6 * depth;
+
+       code = buf = mono_global_codeman_reserve (tramp_size);
+
+       rgctx_null_jumps = g_malloc (sizeof (guint8*) * (depth + 2));
 
-       /* is slot null? */
+       /* load vtable ptr */
+       x86_mov_reg_membase (buf, X86_EAX, X86_ESP, 4, 4);
+       /* load rgctx ptr from vtable */
+       x86_mov_reg_membase (buf, X86_EAX, X86_EAX, G_STRUCT_OFFSET (MonoVTable, runtime_generic_context), 4);
+       /* is the rgctx ptr null? */
        x86_test_reg_reg (buf, X86_EAX, X86_EAX);
-       jump = buf;
        /* if yes, jump to actual trampoline */
+       rgctx_null_jumps [0] = buf;
        x86_branch8 (buf, X86_CC_Z, -1, 1);
 
-       /* if no, just return */
+       for (i = 0; i < depth; ++i) {
+               /* load ptr to next array */
+               x86_mov_reg_membase (buf, X86_EAX, X86_EAX, 0, 4);
+               /* is the ptr null? */
+               x86_test_reg_reg (buf, X86_EAX, X86_EAX);
+               /* if yes, jump to actual trampoline */
+               rgctx_null_jumps [i + 1] = buf;
+               x86_branch8 (buf, X86_CC_Z, -1, 1);
+       }
+
+       /* fetch slot */
+       x86_mov_reg_membase (buf, X86_EAX, X86_EAX, sizeof (gpointer) * (index + 1), 4);
+       /* is the slot null? */
+       x86_test_reg_reg (buf, X86_EAX, X86_EAX);
+       /* if yes, jump to actual trampoline */
+       rgctx_null_jumps [depth + 1] = buf;
+       x86_branch8 (buf, X86_CC_Z, -1, 1);
+       /* otherwise return */
        x86_ret (buf);
 
+       for (i = 0; i <= depth + 1; ++i)
+               x86_patch (rgctx_null_jumps [i], buf);
+
+       g_free (rgctx_null_jumps);
+
        /*
         * our stack looks like this (tos on top):
         *
-        * | ret addr  |
-        * | rgctx ptr |
-        * | ...       |
+        * | ret addr   |
+        * | vtable ptr |
+        * | ...        |
         *
         * the trampoline code expects it to look like this:
         *
-        * | rgctx ptr |
-        * | ret addr  |
-        * | ...       |
+        * | vtable ptr |
+        * | ret addr   |
+        * | ...        |
         *
         * whereas our caller expects to still have one argument on
         * the stack when we return, so we transform the stack into
         * this:
         *
-        * | rgctx ptr |
-        * | ret addr  |
-        * | dummy     |
-        * | ...       |
+        * | vtable ptr |
+        * | ret addr   |
+        * | dummy      |
+        * | ...        |
         *
-        * which actually only requires us to push the rgctx ptr, and
-        * the "old" rgctx ptr becomes the dummy.
+        * which actually only requires us to push the vtable ptr, and
+        * the "old" vtable ptr becomes the dummy.
         */
 
-       x86_patch (jump, buf);
        x86_push_membase (buf, X86_ESP, 4);
 
-       x86_mov_reg_imm (buf, X86_EAX, encoded_offset);
+       x86_mov_reg_imm (buf, X86_EAX, slot);
        x86_jump_code (buf, tramp);
 
        mono_arch_flush_icache (code, buf - code);
 
-       g_assert (buf - code <= 32);
+       g_assert (buf - code <= tramp_size);
 
        return code;
 }