Reorganize the way jump_target_hash is stored in the JIT. Free entries in jump_target...
authorZoltan Varga <vargaz@gmail.com>
Sat, 19 Feb 2011 21:22:03 +0000 (22:22 +0100)
committerZoltan Varga <vargaz@gmail.com>
Sat, 19 Feb 2011 21:23:32 +0000 (22:23 +0100)
mono/mini/mini.c
mono/mini/mini.h

index 4e221b9d9e0e7808eb67a0d874c4f1c28af159b9..a5518150592cc6c4e2d1b992098898223144f0dd 100644 (file)
@@ -3407,7 +3407,7 @@ mono_postprocess_patches (MonoCompile *cfg)
                        break;
                }
                case MONO_PATCH_INFO_METHOD_JUMP: {
-                       GSList *list;
+                       MonoJumpList *jlist;
                        MonoDomain *domain = cfg->domain;
                        unsigned char *ip = cfg->native_code + patch_info->ip.i;
 #if defined(__native_client__) && defined(__native_client_codegen__)
@@ -3418,11 +3418,12 @@ mono_postprocess_patches (MonoCompile *cfg)
 #endif
 
                        mono_domain_lock (domain);
-                       if (!domain_jit_info (domain)->jump_target_hash)
-                               domain_jit_info (domain)->jump_target_hash = g_hash_table_new (NULL, NULL);
-                       list = g_hash_table_lookup (domain_jit_info (domain)->jump_target_hash, patch_info->data.method);
-                       list = g_slist_prepend (list, ip);
-                       g_hash_table_insert (domain_jit_info (domain)->jump_target_hash, patch_info->data.method, list);
+                       jlist = g_hash_table_lookup (domain_jit_info (domain)->jump_target_hash, patch_info->data.method);
+                       if (!jlist) {
+                               jlist = mono_domain_alloc0 (domain, sizeof (MonoJumpList));
+                               g_hash_table_insert (domain_jit_info (domain)->jump_target_hash, patch_info->data.method, jlist);
+                       }
+                       jlist->list = g_slist_prepend (jlist->list, ip);
                        mono_domain_unlock (domain);
                        break;
                }
@@ -5259,18 +5260,19 @@ mono_jit_compile_method_inner (MonoMethod *method, MonoDomain *target_domain, in
 #ifndef DISABLE_JIT
        if (domain_jit_info (target_domain)->jump_target_hash) {
                MonoJumpInfo patch_info;
-               GSList *list, *tmp;
-               list = g_hash_table_lookup (domain_jit_info (target_domain)->jump_target_hash, method);
-               if (list) {
+               MonoJumpList *jlist;
+               GSList *tmp;
+               jlist = g_hash_table_lookup (domain_jit_info (target_domain)->jump_target_hash, method);
+               if (jlist) {
                        patch_info.next = NULL;
                        patch_info.ip.i = 0;
                        patch_info.type = MONO_PATCH_INFO_METHOD_JUMP;
                        patch_info.data.method = method;
                        g_hash_table_remove (domain_jit_info (target_domain)->jump_target_hash, method);
+
+                       for (tmp = jlist->list; tmp; tmp = tmp->next)
+                               mono_arch_patch_code (NULL, target_domain, tmp->data, &patch_info, TRUE);
                }
-               for (tmp = list; tmp; tmp = tmp->next)
-                       mono_arch_patch_code (NULL, target_domain, tmp->data, &patch_info, TRUE);
-               g_slist_free (list);
        }
 
        mono_emit_jit_map (jinfo);
@@ -5410,6 +5412,8 @@ mono_jit_free_method (MonoDomain *domain, MonoMethod *method)
 {
        MonoJitDynamicMethodInfo *ji;
        gboolean destroy = TRUE;
+       GHashTableIter iter;
+       MonoJumpList *jlist;
 
        g_assert (method->dynamic);
 
@@ -5419,11 +5423,31 @@ mono_jit_free_method (MonoDomain *domain, MonoMethod *method)
 
        if (!ji)
                return;
+
        mono_domain_lock (domain);
        g_hash_table_remove (domain_jit_info (domain)->dynamic_code_hash, method);
        mono_internal_hash_table_remove (&domain->jit_code_hash, method);
        g_hash_table_remove (domain_jit_info (domain)->jump_trampoline_hash, method);
        g_hash_table_remove (domain_jit_info (domain)->runtime_invoke_hash, method);
+
+       /* Remove jump targets in this method */
+       g_hash_table_iter_init (&iter, domain_jit_info (domain)->jump_target_hash);
+       while (g_hash_table_iter_next (&iter, NULL, (void**)&jlist)) {
+               GSList *tmp, *remove;
+
+               remove = NULL;
+               for (tmp = jlist->list; tmp; tmp = tmp->next) {
+                       guint8 *ip = tmp->data;
+
+                       if (ip >= (guint8*)ji->ji->code_start && ip < (guint8*)ji->ji->code_start + ji->ji->code_size)
+                               remove = g_slist_prepend (remove, tmp);
+               }
+               for (tmp = remove; tmp; tmp = tmp->next) {
+                       jlist->list = g_slist_delete_link (jlist->list, tmp->data);
+               }
+               g_slist_free (remove);
+       }
+
        mono_domain_unlock (domain);
 
 #ifdef MONO_ARCH_HAVE_INVALIDATE_METHOD
@@ -6055,6 +6079,7 @@ mini_create_jit_domain_info (MonoDomain *domain)
        info->runtime_invoke_hash = g_hash_table_new_full (mono_aligned_addr_hash, NULL, NULL, runtime_invoke_info_free);
        info->seq_points = g_hash_table_new_full (mono_aligned_addr_hash, NULL, NULL, g_free);
        info->arch_seq_points = g_hash_table_new (mono_aligned_addr_hash, NULL);
+       info->jump_target_hash = g_hash_table_new (NULL, NULL);
 
        domain->runtime_info = info;
 }
@@ -6062,7 +6087,8 @@ mini_create_jit_domain_info (MonoDomain *domain)
 static void
 delete_jump_list (gpointer key, gpointer value, gpointer user_data)
 {
-       g_slist_free (value);
+       MonoJumpList *jlist = value;
+       g_slist_free (jlist->list);
 }
 
 static void
@@ -6090,10 +6116,8 @@ mini_free_jit_domain_info (MonoDomain *domain)
 {
        MonoJitDomainInfo *info = domain_jit_info (domain);
 
-       if (info->jump_target_hash) {
-               g_hash_table_foreach (info->jump_target_hash, delete_jump_list, NULL);
-               g_hash_table_destroy (info->jump_target_hash);
-       }
+       g_hash_table_foreach (info->jump_target_hash, delete_jump_list, NULL);
+       g_hash_table_destroy (info->jump_target_hash);
        if (info->jump_target_got_slot_hash) {
                g_hash_table_foreach (info->jump_target_got_slot_hash, delete_jump_list, NULL);
                g_hash_table_destroy (info->jump_target_got_slot_hash);
index 712fb5053e3637c51a4efae66f02f9147706479f..e21afeb61f12407141581ce14acaa8d09ea767a9 100644 (file)
@@ -267,6 +267,11 @@ typedef struct {
 
 #define domain_jit_info(domain) ((MonoJitDomainInfo*)((domain)->runtime_info))
 
+/* Contains a list of ips which needs to be patched when a method is compiled */
+typedef struct {
+       GSList *list;
+} MonoJumpList;
+
 /* Arch-specific */
 typedef struct {
        int dummy;