diff options
author | Zoltan Varga <vargaz@gmail.com> | 2016-10-14 18:31:56 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2016-10-14 18:31:56 +0300 |
commit | 0cbbc88be021dda65aac48f43ab17b4272bec79b (patch) | |
tree | 82e3a64e56096a4c8b5944fc36e3e5f683daec88 | |
parent | 6cfb6363e7f1fdb4c58f485b194a0966c916e40f (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.h | 3 | ||||
-rw-r--r-- | mono/metadata/domain.c | 4 | ||||
-rw-r--r-- | mono/metadata/object.c | 142 |
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); |