2008-05-26 Zoltan Varga <vargaz@gmail.com>
authorZoltan Varga <vargaz@gmail.com>
Mon, 26 May 2008 10:16:14 +0000 (10:16 -0000)
committerZoltan Varga <vargaz@gmail.com>
Mon, 26 May 2008 10:16:14 +0000 (10:16 -0000)
* class.c (mono_method_set_generic_container): New accessor function.
(mono_method_get_generic_container): Ditto.

* class-internals.h (struct _MonoMethod): Remove rarely used
'generic_container' field, store it in the property hash instead. Add
'is_generic' boolean field instead.

* image.c (mono_image_init): Initialize property_hash.
(mono_image_close): Destroy property_hash.

* metadata-internals.h (struct _MonoImage): Add 'property_hash' hash table to
hold rarely used fields of runtime structures belonging to this image.

* class.c loader.c verify.c icall.c reflection.c: Use the new accessor functions
to get/set method->generic_container.

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

mono/metadata/ChangeLog
mono/metadata/class-internals.h
mono/metadata/class.c
mono/metadata/icall.c
mono/metadata/image.c
mono/metadata/loader.c
mono/metadata/metadata-internals.h
mono/metadata/reflection.c
mono/metadata/verify.c

index 66ad93b01a36d79600e5435ab2e0fb5e098e1378..cc11c0345e03ed83412dd79e9720a1985d344788 100644 (file)
@@ -1,5 +1,21 @@
 2008-05-26  Zoltan Varga  <vargaz@gmail.com>
 
+       * class.c (mono_method_set_generic_container): New accessor function.
+       (mono_method_get_generic_container): Ditto.
+
+       * class-internals.h (struct _MonoMethod): Remove rarely used 
+       'generic_container' field, store it in the property hash instead. Add 
+       'is_generic' boolean field instead.
+
+       * image.c (mono_image_init): Initialize property_hash.
+       (mono_image_close): Destroy property_hash.
+
+       * metadata-internals.h (struct _MonoImage): Add 'property_hash' hash table to
+       hold rarely used fields of runtime structures belonging to this image.
+
+       * class.c loader.c verify.c icall.c reflection.c: Use the new accessor functions
+       to get/set method->generic_container.
+
        * loader.c (mono_get_method_from_token): Avoid loading the method header for
        generic methods.
 
index 5a16729094f9f961bdfc7b6fc5174429a8edfb99..e40eb69bba4b2a5e2811b8573032824b41a0eb67 100644 (file)
@@ -41,13 +41,14 @@ typedef enum {
        MONO_REMOTING_TARGET_COMINTEROP
 } MonoRemotingTarget;
 
+#define MONO_METHOD_PROP_GENERIC_CONTAINER 0
+
 struct _MonoMethod {
        guint16 flags;  /* method flags */
        guint16 iflags; /* method implementation flags */
        guint32 token;
        MonoClass *klass;
        MonoMethodSignature *signature;
-       MonoGenericContainer *generic_container;
        /* name is useful mostly for debugging */
        const char *name;
        /* this is used by the inlining algorithm */
@@ -57,10 +58,16 @@ struct _MonoMethod {
        unsigned int string_ctor:1;
        unsigned int save_lmf:1;
        unsigned int dynamic:1; /* created & destroyed during runtime */
+       unsigned int is_generic:1; /* whenever this is a generic method definition */
        unsigned int is_inflated:1; /* whether we're a MonoMethodInflated */
        unsigned int skip_visibility:1; /* whenever to skip JIT visibility checks */
        unsigned int verification_success:1; /* whether this method has been verified successfully.*/
-       signed int slot : 19;
+       signed int slot : 18;
+
+       /*
+        * If is_generic is TRUE, the generic_container is stored in image->property_hash, 
+        * using the key MONO_METHOD_PROP_GENERIC_CONTAINER.
+        */
 };
 
 struct _MonoMethodNormal {
@@ -736,12 +743,19 @@ mono_class_get_context (MonoClass *class) MONO_INTERNAL;
 MonoGenericContext*
 mono_method_get_context (MonoMethod *method) MONO_INTERNAL;
 
+/* Used by monodis, thus cannot be MONO_INTERNAL */
+MonoGenericContainer*
+mono_method_get_generic_container (MonoMethod *method);
+
 MonoGenericContext*
 mono_generic_class_get_context (MonoGenericClass *gclass) MONO_INTERNAL;
 
 MonoClass*
 mono_generic_class_get_class (MonoGenericClass *gclass) MONO_INTERNAL;
 
+void
+mono_method_set_generic_container (MonoMethod *method, MonoGenericContainer* container) MONO_INTERNAL;
+
 MonoMethod*
 mono_class_inflate_generic_method_full (MonoMethod *method, MonoClass *klass_hint, MonoGenericContext *context);
 
index f7fd00405ff76ed3627950fd368d5e0b8cc2137a..b637c33d8caccfa739547de5ccd5709a2bb07140 100644 (file)
@@ -665,7 +665,7 @@ mono_class_inflate_generic_method_full (MonoMethod *method, MonoClass *klass_hin
                method = imethod->declaring;
        }
 
-       if (!method->generic_container && !method->klass->generic_container)
+       if (!method->is_generic && !method->klass->generic_container)
                return method;
 
        /*
@@ -698,17 +698,17 @@ mono_class_inflate_generic_method_full (MonoMethod *method, MonoClass *klass_hin
         * everything should behave like a regular type or method.
         * 
         */
-       is_mb_open = method->generic_container && /* This is a generic method definition */
+       is_mb_open = method->is_generic &&
                method->klass->image->dynamic && !method->klass->wastypebuilder && /* that is a MethodBuilder from an unfinished TypeBuilder */
-               context->method_inst == method->generic_container->context.method_inst; /* and it's been instantiated with its own arguments.  */
+               context->method_inst == mono_method_get_generic_container (method)->context.method_inst; /* and it's been instantiated with its own arguments.  */
 
        iresult = g_new0 (MonoMethodInflated, 1);
        iresult->context = *context;
        iresult->declaring = method;
        iresult->is_mb_open = is_mb_open;
 
-       if (!context->method_inst && method->generic_container)
-               iresult->context.method_inst = method->generic_container->context.method_inst;
+       if (!context->method_inst && method->is_generic)
+               iresult->context.method_inst = mono_method_get_generic_container (method)->context.method_inst;
 
        mono_loader_lock ();
        cached = mono_method_inflated_lookup (iresult, FALSE);
@@ -729,13 +729,19 @@ mono_class_inflate_generic_method_full (MonoMethod *method, MonoClass *klass_hin
        }
 
        result = (MonoMethod *) iresult;
-       result->is_inflated = 1;
+       result->is_inflated = TRUE;
+       result->is_generic = FALSE;
        result->signature = NULL;
 
-       if (context->method_inst)
-               result->generic_container = NULL;
+       if (!context->method_inst) {
+               /* Set the generic_container of the result to the generic_container of method */
+               MonoGenericContainer *generic_container = mono_method_get_generic_container (method);
 
-       /* Due to the memcpy above, !context->method_inst => result->generic_container == method->generic_container */
+               if (generic_container) {
+                       result->is_generic = 1;
+                       mono_method_set_generic_container (result, generic_container);
+               }
+       }
 
        if (!klass_hint || !klass_hint->generic_class ||
            klass_hint->generic_class->container_class != method->klass ||
@@ -778,6 +784,45 @@ mono_method_get_context (MonoMethod *method)
        return &imethod->context;
 }
 
+/*
+ * mono_method_get_generic_container:
+ *
+ *   Returns the generic container of METHOD, which should be a generic method definition.
+ * Returns NULL if METHOD is not a generic method definition.
+ * LOCKING: Acquires the loader lock.
+ */
+MonoGenericContainer*
+mono_method_get_generic_container (MonoMethod *method)
+{
+       MonoGenericContainer *container;
+
+       if (!method->is_generic)
+               return NULL;
+
+       mono_loader_lock ();
+       container = mono_property_hash_lookup (method->klass->image->property_hash, method, MONO_METHOD_PROP_GENERIC_CONTAINER);
+       mono_loader_unlock ();
+       g_assert (container);
+
+       return container;
+}
+
+/*
+ * mono_method_set_generic_container:
+ *
+ *   Sets the generic container of METHOD to CONTAINER.
+ * LOCKING: Acquires the loader lock.
+ */
+void
+mono_method_set_generic_container (MonoMethod *method, MonoGenericContainer* container)
+{
+       g_assert (method->is_generic);
+
+       mono_loader_lock ();
+       mono_property_hash_insert (method->klass->image->property_hash, method, MONO_METHOD_PROP_GENERIC_CONTAINER, container);
+       mono_loader_unlock ();
+}
+
 /** 
  * mono_class_find_enum_basetype:
  * @class: The enum class
index f039a07fd101694e7fd4dcec8f8001a372c17448..5c58f585aafc75d9c6bc4744581afbb15dedbad0 100644 (file)
@@ -2729,7 +2729,7 @@ ves_icall_MonoMethod_GetGenericMethodDefinition (MonoReflectionMethod *method)
 
        MONO_ARCH_SAVE_REGS;
 
-       if (method->method->generic_container)
+       if (method->method->is_generic)
                return method;
 
        if (!method->method->is_inflated)
@@ -2739,7 +2739,7 @@ ves_icall_MonoMethod_GetGenericMethodDefinition (MonoReflectionMethod *method)
 
        result = imethod->declaring;
        /* Not a generic method.  */
-       if (!result->generic_container)
+       if (!result->is_generic)
                return NULL;
 
        if (method->method->klass->image->dynamic) {
@@ -2779,7 +2779,7 @@ ves_icall_MonoMethod_get_IsGenericMethodDefinition (MonoReflectionMethod *method
 {
        MONO_ARCH_SAVE_REGS;
 
-       return method->method->generic_container != NULL;
+       return method->method->is_generic;
 }
 
 static MonoArray*
@@ -2810,7 +2810,8 @@ ves_icall_MonoMethod_GetGenericArguments (MonoReflectionMethod *method)
        res = mono_array_new (domain, mono_defaults.monotype_class, count);
 
        for (i = 0; i < count; i++) {
-               MonoGenericParam *param = &method->method->generic_container->type_params [i];
+               MonoGenericContainer *container = mono_method_get_generic_container (method->method);
+               MonoGenericParam *param = &container->type_params [i];
                MonoClass *pklass = mono_class_from_generic_parameter (
                        param, method->method->klass->image, TRUE);
                mono_array_setref (res, i,
index f0c4dd290e1d5f87af96c26a6c261a2398655ff0..ed4df0f6641104cb8ffa5103e131299be303494a 100644 (file)
@@ -642,6 +642,8 @@ mono_image_init (MonoImage *image)
        image->memberref_signatures = g_hash_table_new (NULL, NULL);
        image->helper_signatures = g_hash_table_new (g_str_hash, g_str_equal);
        image->method_signatures = g_hash_table_new (NULL, NULL);
+
+       image->property_hash = mono_property_hash_new ();
 }
 
 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
@@ -1500,6 +1502,9 @@ mono_image_close (MonoImage *image)
        if (image->rgctx_template_hash)
                g_hash_table_destroy (image->rgctx_template_hash);
 
+       if (image->property_hash)
+               mono_property_hash_destroy (image->property_hash);
+
        if (image->interface_bitset) {
                mono_unload_interface_ids (image->interface_bitset);
                mono_bitset_free (image->interface_bitset);
index efd7916e8713fe7235e284ae6bfb4abcc694d7ab..799ca10d565c0f580689bc05c394dce255aaa8d6 100644 (file)
@@ -1374,6 +1374,7 @@ mono_get_method_from_token (MonoImage *image, guint32 token, MonoClass *klass,
        container = klass->generic_container;
        generic_container = mono_metadata_load_generic_params (image, token, container);
        if (generic_container) {
+               result->is_generic = TRUE;
                generic_container->owner.method = result;
 
                mono_metadata_load_generic_param_constraints (image, token, generic_container);
@@ -1408,7 +1409,8 @@ mono_get_method_from_token (MonoImage *image, guint32 token, MonoClass *klass,
                        piinfo->piflags = mono_metadata_decode_row_col (&tables [MONO_TABLE_IMPLMAP], piinfo->implmap_idx - 1, MONO_IMPLMAP_FLAGS);
        }
 
-       result->generic_container = generic_container;
+       if (generic_container)
+               mono_method_set_generic_container (result, generic_container);
 
        return result;
 }
@@ -1556,6 +1558,10 @@ mono_free_method  (MonoMethod *method)
                MonoMethodWrapper *mw = (MonoMethodWrapper*)method;
                int i;
 
+               mono_loader_lock ();
+               mono_property_hash_remove_object (method->klass->image->property_hash, method);
+               mono_loader_unlock ();
+
                g_free ((char*)method->name);
                if (mw->method.header) {
                        g_free ((char*)mw->method.header->code);
@@ -1873,7 +1879,7 @@ mono_method_signature (MonoMethod *m)
        sig = mono_metadata_blob_heap (img, mono_metadata_decode_row_col (&img->tables [MONO_TABLE_METHOD], idx - 1, MONO_METHOD_SIGNATURE));
 
        g_assert (!m->klass->generic_class);
-       container = m->generic_container;
+       container = mono_method_get_generic_container (m);
        if (!container)
                container = m->klass->generic_container;
 
@@ -2018,7 +2024,7 @@ mono_method_get_header (MonoMethod *method)
 
        g_assert (loc);
 
-       mn->header = mono_metadata_parse_mh_full (img, method->generic_container, loc);
+       mn->header = mono_metadata_parse_mh_full (img, mono_method_get_generic_container (method), loc);
 
        mono_loader_unlock ();
        return mn->header;
index 40fa8ca7e46ce4ae077996cf23a4ea3a521d7b7f..267d0cf6544fb72dc6ebd202e1a7f58f65f813ac 100644 (file)
@@ -10,6 +10,7 @@
 #include "mono/utils/mono-compiler.h"
 #include "mono/utils/mono-dl.h"
 #include "mono/utils/monobitset.h"
+#include "mono/utils/mono-property-hash.h"
 
 #define MONO_SECMAN_FLAG_INIT(x)               (x & 0x2)
 #define MONO_SECMAN_FLAG_GET_VALUE(x)          (x & 0x1)
@@ -217,6 +218,9 @@ struct _MonoImage {
         */
        GHashTable *generic_class_cache;
 
+       /* Contains rarely used fields of runtime structures belonging to this image */
+       MonoPropertyHash *property_hash;
+
        void *reflection_info;
 
        /*
index 81e7a16349887c160298e2292941c9f7e794e05e..f2a528fe0a097084fa0dee9ac720d81be9eb2306 100644 (file)
@@ -8909,7 +8909,11 @@ reflection_methodbuilder_to_mono_method (MonoClass *klass,
                int count = mono_array_length (rmb->generic_params);
                MonoGenericContainer *container;
 
-               m->generic_container = container = rmb->generic_container;
+               container = rmb->generic_container;
+               if (container) {
+                       m->is_generic = TRUE;
+                       mono_method_set_generic_container (m, container);
+               }
                container->type_argc = count;
                container->type_params = g_new0 (MonoGenericParam, count);
                container->owner.method = m;
@@ -9251,7 +9255,7 @@ inflate_mono_method (MonoClass *klass, MonoMethod *method, MonoObject *obj)
                imethod = (MonoMethodInflated *) mono_class_inflate_generic_method_full (method, klass, context);
        }
 
-       if (method->generic_container && method->klass->image->dynamic) {
+       if (method->is_generic && method->klass->image->dynamic) {
                MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
 
                mono_loader_lock ();
index 9aa1f0eb6d5f95e755c9933eaf4d93f9bf2f56f9..f3a83abd6a0f8e0f38aa990f53fc2aca2a27d7a2 100644 (file)
@@ -469,7 +469,7 @@ mono_method_is_valid_generic_instantiation (MonoMethod *method)
 {
        MonoMethodInflated *gmethod = (MonoMethodInflated *)method;
        MonoGenericInst *ginst = gmethod->context.method_inst;
-       MonoGenericContainer *gc = gmethod->declaring->generic_container;
+       MonoGenericContainer *gc = mono_method_get_generic_container (gmethod->declaring);
        if (!gc) /*non-generic inflated method - it's part of a generic type  */
                return TRUE;
        return is_valid_generic_instantiation (gc, &gmethod->context, ginst);
@@ -4416,9 +4416,9 @@ mono_method_verify (MonoMethod *method, int level)
        if (ctx.signature->is_inflated)
                ctx.generic_context = generic_context = mono_method_get_context (method);
 
-       if (!generic_context && (method->klass->generic_container || method->generic_container)) {
-               if (method->generic_container)
-                       ctx.generic_context = generic_context = &method->generic_container->context;
+       if (!generic_context && (method->klass->generic_container || method->is_generic)) {
+               if (method->is_generic)
+                       ctx.generic_context = generic_context = &(mono_method_get_generic_container (method)->context);
                else
                        ctx.generic_context = generic_context = &method->klass->generic_container->context;
        }