Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/mono.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorZoltan Varga <vargaz@gmail.com>2016-10-14 18:31:56 +0300
committerGitHub <noreply@github.com>2016-10-14 18:31:56 +0300
commit0cbbc88be021dda65aac48f43ab17b4272bec79b (patch)
tree82e3a64e56096a4c8b5944fc36e3e5f683daec88
parent6cfb6363e7f1fdb4c58f485b194a0966c916e40f (diff)
[runtime] Avoid freeing IMT thunks, some threads might still be executing them. This creates a memory leak, but its bounded. Fixes #39832. (#3767)
-rw-r--r--mono/metadata/domain-internals.h3
-rw-r--r--mono/metadata/domain.c4
-rw-r--r--mono/metadata/object.c142
3 files changed, 1 insertions, 148 deletions
diff --git a/mono/metadata/domain-internals.h b/mono/metadata/domain-internals.h
index a3989ab74aa..d4d20ab25a4 100644
--- a/mono/metadata/domain-internals.h
+++ b/mono/metadata/domain-internals.h
@@ -380,9 +380,6 @@ struct _MonoDomain {
GHashTable *method_rgctx_hash;
GHashTable *generic_virtual_cases;
- MonoThunkFreeList **thunk_free_lists;
-
- GHashTable *generic_virtual_thunks;
/* Information maintained by the JIT engine */
gpointer runtime_info;
diff --git a/mono/metadata/domain.c b/mono/metadata/domain.c
index a3ba4a76e04..f18f9b0d0de 100644
--- a/mono/metadata/domain.c
+++ b/mono/metadata/domain.c
@@ -1239,10 +1239,6 @@ mono_domain_free (MonoDomain *domain, gboolean force)
g_hash_table_destroy (domain->generic_virtual_cases);
domain->generic_virtual_cases = NULL;
}
- if (domain->generic_virtual_thunks) {
- g_hash_table_destroy (domain->generic_virtual_thunks);
- domain->generic_virtual_thunks = NULL;
- }
if (domain->ftnptrs_hash) {
g_hash_table_destroy (domain->ftnptrs_hash);
domain->ftnptrs_hash = NULL;
diff --git a/mono/metadata/object.c b/mono/metadata/object.c
index f827cb16009..d5b8dd5db52 100644
--- a/mono/metadata/object.c
+++ b/mono/metadata/object.c
@@ -1549,49 +1549,8 @@ mono_vtable_build_imt_slot (MonoVTable* vtable, int imt_slot)
mono_loader_unlock ();
}
-
-/*
- * The first two free list entries both belong to the wait list: The
- * first entry is the pointer to the head of the list and the second
- * entry points to the last element. That way appending and removing
- * the first element are both O(1) operations.
- */
-#ifdef MONO_SMALL_CONFIG
-#define NUM_FREE_LISTS 6
-#else
-#define NUM_FREE_LISTS 12
-#endif
-#define FIRST_FREE_LIST_SIZE 64
-#define MAX_WAIT_LENGTH 50
#define THUNK_THRESHOLD 10
-/*
- * LOCKING: The domain lock must be held.
- */
-static void
-init_thunk_free_lists (MonoDomain *domain)
-{
- MONO_REQ_GC_NEUTRAL_MODE;
-
- if (domain->thunk_free_lists)
- return;
- domain->thunk_free_lists = (MonoThunkFreeList **)mono_domain_alloc0 (domain, sizeof (gpointer) * NUM_FREE_LISTS);
-}
-
-static int
-list_index_for_size (int item_size)
-{
- int i = 2;
- int size = FIRST_FREE_LIST_SIZE;
-
- while (item_size > size && i < NUM_FREE_LISTS - 1) {
- i++;
- size <<= 1;
- }
-
- return i;
-}
-
/**
* mono_method_alloc_generic_virtual_thunk:
* @domain: a domain
@@ -1611,36 +1570,6 @@ mono_method_alloc_generic_virtual_thunk (MonoDomain *domain, int size)
static gboolean inited = FALSE;
static int generic_virtual_thunks_size = 0;
- guint32 *p;
- int i;
- MonoThunkFreeList **l;
-
- init_thunk_free_lists (domain);
-
- size += sizeof (guint32);
- if (size < sizeof (MonoThunkFreeList))
- size = sizeof (MonoThunkFreeList);
-
- i = list_index_for_size (size);
- for (l = &domain->thunk_free_lists [i]; *l; l = &(*l)->next) {
- if ((*l)->size >= size) {
- MonoThunkFreeList *item = *l;
- *l = item->next;
- return ((guint32*)item) + 1;
- }
- }
-
- /* no suitable item found - search lists of larger sizes */
- while (++i < NUM_FREE_LISTS) {
- MonoThunkFreeList *item = domain->thunk_free_lists [i];
- if (!item)
- continue;
- g_assert (item->size > size);
- domain->thunk_free_lists [i] = item->next;
- return ((guint32*)item) + 1;
- }
-
- /* still nothing found - allocate it */
if (!inited) {
mono_counters_register ("Generic virtual thunk bytes",
MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &generic_virtual_thunks_size);
@@ -1648,68 +1577,7 @@ mono_method_alloc_generic_virtual_thunk (MonoDomain *domain, int size)
}
generic_virtual_thunks_size += size;
- p = (guint32 *)mono_domain_code_reserve (domain, size);
- *p = size;
-
- mono_domain_lock (domain);
- if (!domain->generic_virtual_thunks)
- domain->generic_virtual_thunks = g_hash_table_new (NULL, NULL);
- g_hash_table_insert (domain->generic_virtual_thunks, p, p);
- mono_domain_unlock (domain);
-
- return p + 1;
-}
-
-/*
- * LOCKING: The domain lock must be held.
- */
-static void
-invalidate_generic_virtual_thunk (MonoDomain *domain, gpointer code)
-{
- MONO_REQ_GC_NEUTRAL_MODE;
-
- guint32 *p = (guint32 *)code;
- MonoThunkFreeList *l = (MonoThunkFreeList*)(p - 1);
- gboolean found = FALSE;
-
- mono_domain_lock (domain);
- if (!domain->generic_virtual_thunks)
- domain->generic_virtual_thunks = g_hash_table_new (NULL, NULL);
- if (g_hash_table_lookup (domain->generic_virtual_thunks, l))
- found = TRUE;
- mono_domain_unlock (domain);
-
- if (!found)
- /* Not allocated by mono_method_alloc_generic_virtual_thunk (), i.e. AOT */
- return;
- init_thunk_free_lists (domain);
-
- while (domain->thunk_free_lists [0] && domain->thunk_free_lists [0]->length >= MAX_WAIT_LENGTH) {
- MonoThunkFreeList *item = domain->thunk_free_lists [0];
- int length = item->length;
- int i;
-
- /* unlink the first item from the wait list */
- domain->thunk_free_lists [0] = item->next;
- domain->thunk_free_lists [0]->length = length - 1;
-
- i = list_index_for_size (item->size);
-
- /* put it in the free list */
- item->next = domain->thunk_free_lists [i];
- domain->thunk_free_lists [i] = item;
- }
-
- l->next = NULL;
- if (domain->thunk_free_lists [1]) {
- domain->thunk_free_lists [1] = domain->thunk_free_lists [1]->next = l;
- domain->thunk_free_lists [0]->length++;
- } else {
- g_assert (!domain->thunk_free_lists [0]);
-
- domain->thunk_free_lists [0] = domain->thunk_free_lists [1] = l;
- domain->thunk_free_lists [0]->length = 1;
- }
+ return mono_domain_code_reserve (domain, size);
}
typedef struct _GenericVirtualCase {
@@ -1821,7 +1689,6 @@ mono_method_add_generic_virtual_invocation (MonoDomain *domain, MonoVTable *vtab
}
if (++gvc->count == THUNK_THRESHOLD) {
- gpointer *old_thunk = (void **)*vtable_slot;
gpointer vtable_trampoline = NULL;
gpointer imt_trampoline = NULL;
@@ -1852,13 +1719,6 @@ mono_method_add_generic_virtual_invocation (MonoDomain *domain, MonoVTable *vtab
g_free (g_ptr_array_index (sorted, i));
g_ptr_array_free (sorted, TRUE);
}
-
-#ifndef __native_client__
- /* We don't re-use any thunks as there is a lot of overhead */
- /* to deleting and re-using code in Native Client. */
- if (old_thunk != vtable_trampoline && old_thunk != imt_trampoline)
- invalidate_generic_virtual_thunk (domain, old_thunk);
-#endif
}
mono_domain_unlock (domain);