Author: zoltan
Date: 2007-09-18 11:41:31 -0400 (Tue, 18 Sep 2007)
New Revision: 85977

Modified:
   trunk/mono/mono/metadata/ChangeLog
   trunk/mono/mono/metadata/class-internals.h
   trunk/mono/mono/metadata/loader.c
   trunk/mono/mono/metadata/metadata.c
Log:
2007-09-18  Zoltan Varga  <[EMAIL PROTECTED]>

        * metadata.c (mono_metadata_get_inflated_signature): New function to 
return a
        canonical instance of an inflated generic signature.
        (mono_type_create_from_typespec): Remove an invalid free.

        * loader.c (mono_method_get_signature_full): Use 
mono_metadata_get_inflated_signature.  


Modified: trunk/mono/mono/metadata/ChangeLog
===================================================================
--- trunk/mono/mono/metadata/ChangeLog  2007-09-18 15:24:45 UTC (rev 85976)
+++ trunk/mono/mono/metadata/ChangeLog  2007-09-18 15:41:31 UTC (rev 85977)
@@ -1,3 +1,11 @@
+2007-09-18  Zoltan Varga  <[EMAIL PROTECTED]>
+
+       * metadata.c (mono_metadata_get_inflated_signature): New function to 
return a
+       canonical instance of an inflated generic signature.
+       (mono_type_create_from_typespec): Remove an invalid free.
+
+       * loader.c (mono_method_get_signature_full): Use 
mono_metadata_get_inflated_signature.  
+
 2007-09-18  Marek Habersack  <[EMAIL PROTECTED]>
 
        * domain-internals.h: added a declaration of the

Modified: trunk/mono/mono/metadata/class-internals.h
===================================================================
--- trunk/mono/mono/metadata/class-internals.h  2007-09-18 15:24:45 UTC (rev 
85976)
+++ trunk/mono/mono/metadata/class-internals.h  2007-09-18 15:41:31 UTC (rev 
85977)
@@ -656,6 +656,12 @@
 MonoMethodInflated*
 mono_method_inflated_lookup (MonoMethodInflated* method, gboolean cache) 
MONO_INTERNAL;
 
+MonoMethodSignature *
+mono_metadata_get_inflated_signature (MonoMethodSignature *sig, 
MonoGenericContext *context);
+
+void
+mono_metadata_free_inflated_signature (MonoMethodSignature *sig);
+
 typedef struct {
        MonoImage *corlib;
        MonoClass *object_class;

Modified: trunk/mono/mono/metadata/loader.c
===================================================================
--- trunk/mono/mono/metadata/loader.c   2007-09-18 15:24:45 UTC (rev 85976)
+++ trunk/mono/mono/metadata/loader.c   2007-09-18 15:41:31 UTC (rev 85977)
@@ -661,7 +661,6 @@
                prev_sig = g_hash_table_lookup (image->memberref_signatures, 
GUINT_TO_POINTER (token));
                if (prev_sig) {
                        /* Somebody got in before us */
-                       /* FIXME: Free sig */
                        sig = prev_sig;
                }
                else
@@ -669,8 +668,17 @@
                mono_loader_unlock ();
        }
 
-       sig = inflate_generic_signature (image, sig, context);
+       if (context) {
+               MonoMethodSignature *cached;
 
+               /* This signature is not owned by a MonoMethod, so need to 
cache */
+               sig = inflate_generic_signature (image, sig, context);
+               cached = mono_metadata_get_inflated_signature (sig, context);
+               if (cached != sig)
+                       mono_metadata_free_inflated_signature (sig);
+               sig = cached;
+       }
+
        return sig;
 }
 

Modified: trunk/mono/mono/metadata/metadata.c
===================================================================
--- trunk/mono/mono/metadata/metadata.c 2007-09-18 15:24:45 UTC (rev 85976)
+++ trunk/mono/mono/metadata/metadata.c 2007-09-18 15:41:31 UTC (rev 85977)
@@ -435,6 +435,12 @@
 
 #endif
 
+/* Auxiliary structure used for caching inflated signatures */
+typedef struct {
+       MonoMethodSignature *sig;
+       MonoGenericContext context;
+} MonoInflatedMethodSignature;
+
 /**
  * mono_meta_table_name:
  * @table: table index
@@ -1353,6 +1359,12 @@
  */
 static GHashTable *generic_method_cache = NULL;
 
+/*
+ * Protected by the loader lock.
+ * It has a MonoInflatedMethodSignature* as key and value.
+ */
+static GHashTable *generic_signature_cache = NULL;
+
 static guint mono_generic_class_hash (gconstpointer data);
 
 /*
@@ -1465,10 +1477,13 @@
        g_hash_table_destroy (generic_class_cache);
        if (generic_method_cache)
                g_hash_table_destroy (generic_method_cache);
+       if (generic_signature_cache)
+               g_hash_table_destroy (generic_signature_cache);
        type_cache = NULL;
        generic_inst_cache = NULL;
        generic_class_cache = NULL;
        generic_method_cache = NULL;
+       generic_signature_cache = NULL;
 }
 
 /**
@@ -1903,6 +1918,22 @@
        */
 }
 
+void
+mono_metadata_free_inflated_signature (MonoMethodSignature *sig)
+{
+       int i;
+
+       /* Allocated in inflate_generic_signature () */
+       if (sig->ret)
+               mono_metadata_free_type (sig->ret);
+       for (i = 0; i < sig->param_count; ++i) {
+               if (sig->params [i])
+                       mono_metadata_free_type (sig->params [i]);
+       }
+       /* FIXME: The signature is allocated from a mempool */
+       //g_free (sig);
+}
+
 static gboolean
 inflated_method_equal (gconstpointer a, gconstpointer b)
 {
@@ -1920,6 +1951,28 @@
        return mono_metadata_generic_context_hash (&ma->context) ^ 
mono_aligned_addr_hash (ma->declaring);
 }
 
+static gboolean
+inflated_signature_equal (gconstpointer a, gconstpointer b)
+{
+       const MonoInflatedMethodSignature *sig1 = a;
+       const MonoInflatedMethodSignature *sig2 = b;
+
+       /* sig->sig is assumed to be canonized */
+       if (sig1->sig != sig2->sig)
+               return FALSE;
+       /* The generic instances are canonized */
+       return mono_metadata_generic_context_equal (&sig1->context, 
&sig2->context);
+}
+
+static guint
+inflated_signature_hash (gconstpointer a)
+{
+       const MonoInflatedMethodSignature *sig = a;
+
+       /* sig->sig is assumed to be canonized */
+       return mono_metadata_generic_context_hash (&sig->context) ^ 
mono_aligned_addr_hash (sig->sig);
+}
+
 /*static void
 dump_ginst (MonoGenericInst *ginst)
 {
@@ -2016,24 +2069,18 @@
        return FALSE;
 }
 
-/*
- * LOCKING: assumes the loader lock is held.
- */
-MonoMethodInflated*
-mono_method_inflated_lookup (MonoMethodInflated* method, gboolean cache)
+static gboolean
+inflated_signature_in_image (gpointer key, gpointer value, gpointer data)
 {
-       if (cache) {
-               if (!generic_method_cache)
-                       generic_method_cache = g_hash_table_new_full 
(inflated_method_hash, inflated_method_equal, NULL, 
(GDestroyNotify)free_inflated_method);
-               g_hash_table_insert (generic_method_cache, method, method);
-               return method;
-       } else {
-               if (generic_method_cache)
-                       return g_hash_table_lookup (generic_method_cache, 
method);
-               return NULL;
-       }
-}
+       MonoInflatedMethodSignature *sig = key;
 
+       if (sig->context.class_inst && ginst_in_image (sig->context.class_inst, 
NULL, data))
+               return TRUE;
+       if (sig->context.method_inst && ginst_in_image 
(sig->context.method_inst, NULL, data))
+               return TRUE;
+       return FALSE;
+}      
+
 void
 mono_metadata_clean_for_image (MonoImage *image)
 {
@@ -2051,6 +2098,8 @@
        g_hash_table_foreach_steal (generic_class_cache, gclass_in_image, 
&user_data);
        if (generic_method_cache)
                g_hash_table_foreach_remove (generic_method_cache, 
inflated_method_in_image, &user_data);
+       if (generic_signature_cache)
+               g_hash_table_foreach_remove (generic_signature_cache, 
inflated_signature_in_image, &user_data);
        /* Delete the removed items */
        for (l = user_data.ginst_list; l; l = l->next)
                free_generic_inst (l->data);
@@ -2067,18 +2116,9 @@
        int i;
        MonoMethod *method = (MonoMethod*)imethod;
 
-       if (method->signature) {
-               MonoMethodSignature *sig = method->signature;
+       if (method->signature)
+               mono_metadata_free_inflated_signature (method->signature);
 
-               /* Allocated in inflate_generic_signature () */
-               mono_metadata_free_type (sig->ret);
-               for (i = 0; i < sig->param_count; ++i)
-                       mono_metadata_free_type (sig->params [i]);
-
-               /* FIXME: The signature is allocated from a mempool */
-               //g_free (method->signature);
-       }
-
        if (!((method->flags & METHOD_ATTRIBUTE_ABSTRACT) || (method->iflags & 
METHOD_IMPL_ATTRIBUTE_RUNTIME) || (method->iflags & 
METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) || (method->flags & 
METHOD_ATTRIBUTE_PINVOKE_IMPL))) {
                MonoMethodNormal* mn = (MonoMethodNormal*) method;
                MonoMethodHeader *header = mn->header;
@@ -2133,7 +2173,64 @@
        g_free (gclass);
 }
 
+static void
+free_inflated_signature (MonoInflatedMethodSignature *sig)
+{
+       mono_metadata_free_inflated_signature (sig->sig);
+       g_free (sig);
+}
+
 /*
+ * LOCKING: assumes the loader lock is held.
+ */
+MonoMethodInflated*
+mono_method_inflated_lookup (MonoMethodInflated* method, gboolean cache)
+{
+       if (cache) {
+               if (!generic_method_cache)
+                       generic_method_cache = g_hash_table_new_full 
(inflated_method_hash, inflated_method_equal, NULL, 
(GDestroyNotify)free_inflated_method);
+               g_hash_table_insert (generic_method_cache, method, method);
+               return method;
+       } else {
+               if (generic_method_cache)
+                       return g_hash_table_lookup (generic_method_cache, 
method);
+               return NULL;
+       }
+}
+
+/*
+ * mono_metadata_get_inflated_signature:
+ *
+ *   Given an inflated signature and a generic context, return a canonical 
copy of the 
+ * signature. The returned signature might be equal to SIG or it might be a 
cached copy.
+ */
+MonoMethodSignature *
+mono_metadata_get_inflated_signature (MonoMethodSignature *sig, 
MonoGenericContext *context)
+{
+       MonoInflatedMethodSignature helper;
+       MonoInflatedMethodSignature *res;
+
+       mono_loader_lock ();
+       if (!generic_signature_cache)
+               generic_signature_cache = g_hash_table_new_full 
(inflated_signature_hash, inflated_signature_equal, NULL, 
(GDestroyNotify)free_inflated_signature);
+
+       helper.sig = sig;
+       helper.context.class_inst = context->class_inst;
+       helper.context.method_inst = context->method_inst;
+       res = g_hash_table_lookup (generic_signature_cache, &helper);
+       if (!res) {
+               res = g_new0 (MonoInflatedMethodSignature, 1);
+               res->sig = sig;
+               res->context.class_inst = context->class_inst;
+               res->context.method_inst = context->method_inst;
+               g_hash_table_insert (generic_signature_cache, res, res);
+       }
+
+       mono_loader_unlock ();
+       return res->sig;
+}
+
+/*
  * mono_metadata_get_generic_inst:
  *
  * Given a list of types, return a MonoGenericInst that represents that list.
@@ -4301,7 +4398,6 @@
        type2 = g_hash_table_lookup (image->typespec_cache, GUINT_TO_POINTER 
(type_spec));
 
        if (type2) {
-               g_free (type);
                mono_loader_unlock ();
                return type2;
        }

_______________________________________________
Mono-patches maillist  -  [email protected]
http://lists.ximian.com/mailman/listinfo/mono-patches

Reply via email to