From 6ca11b76d69c197426d6e10aa23b76fc450bea4f Mon Sep 17 00:00:00 2001 From: Jonathan Chambers Date: Tue, 27 Jun 2017 00:45:26 -0400 Subject: [PATCH] Implement GC roots ourselves in Boehm rather than relying on their concept of roots which is mainly for static data segments in binaries and not implemented on all platforms (cannot remove roots on Windows) (#564) --- mono/metadata/boehm-gc.c | 60 +++++++++++++++++++++++++++++++++++----- mono/metadata/domain.c | 2 ++ mono/metadata/sre.c | 2 +- 3 files changed, 56 insertions(+), 8 deletions(-) diff --git a/mono/metadata/boehm-gc.c b/mono/metadata/boehm-gc.c index abbea870830..50ff079d1e2 100644 --- a/mono/metadata/boehm-gc.c +++ b/mono/metadata/boehm-gc.c @@ -56,6 +56,14 @@ void *pthread_get_stackaddr_np(pthread_t); static gboolean gc_initialized = FALSE; static mono_mutex_t mono_gc_lock; +typedef void (*GC_push_other_roots_proc)(void); + +static GC_push_other_roots_proc default_push_other_roots; +static GHashTable *roots; + +static void +mono_push_other_roots(void); + static void register_test_toggleref_callback (void); @@ -167,6 +175,10 @@ mono_gc_base_init (void) } #endif + roots = g_hash_table_new (NULL, NULL); + default_push_other_roots = GC_push_other_roots; + GC_push_other_roots = mono_push_other_roots; + #if !defined(PLATFORM_ANDROID) /* If GC_no_dls is set to true, GC_find_limit is not called. This causes a seg fault on Android. */ GC_no_dls = TRUE; @@ -502,11 +514,27 @@ on_gc_heap_resize (size_t new_size) mono_profiler_gc_heap_resize (new_size); } +typedef struct { + char *start; + char *end; +} RootData; + +static gpointer +register_root (gpointer arg) +{ + RootData* root_data = arg; + g_hash_table_insert (roots, root_data->start, root_data->end); + return NULL; +} + int mono_gc_register_root (char *start, size_t size, void *descr, MonoGCRootSource source, const char *msg) { - /* for some strange reason, they want one extra byte on the end */ - GC_add_roots (start, start + size + 1); + RootData root_data; + root_data.start = start; + /* Boehm root processing requires one byte past end of region to be scanned */ + root_data.end = start + size + 1; + GC_call_with_alloc_lock (register_root, &root_data); return TRUE; } @@ -517,14 +545,32 @@ mono_gc_register_root_wbarrier (char *start, size_t size, MonoGCDescriptor descr return mono_gc_register_root (start, size, descr, source, msg); } +static gpointer +deregister_root (gpointer arg) +{ + gboolean removed = g_hash_table_remove (roots, arg); + g_assert (removed); + return NULL; +} + void mono_gc_deregister_root (char* addr) { -#ifndef HOST_WIN32 - /* FIXME: libgc doesn't define this work win32 for some reason */ - /* FIXME: No size info */ - GC_remove_roots (addr, addr + sizeof (gpointer) + 1); -#endif + GC_call_with_alloc_lock (deregister_root, addr); +} + +static void +push_root (gpointer key, gpointer value, gpointer user_data) +{ + GC_push_all (key, value); +} + +static void +mono_push_other_roots (void) +{ + g_hash_table_foreach (roots, push_root, NULL); + if (default_push_other_roots) + default_push_other_roots (); } static void diff --git a/mono/metadata/domain.c b/mono/metadata/domain.c index 1d353b1da07..16dc31752dd 100644 --- a/mono/metadata/domain.c +++ b/mono/metadata/domain.c @@ -1208,7 +1208,9 @@ mono_domain_free (MonoDomain *domain, gboolean force) domain->setup = NULL; +#ifndef HAVE_BOEHM_GC mono_gc_deregister_root ((char*)&(domain->MONO_DOMAIN_FIRST_GC_TRACKED)); +#endif mono_appdomains_lock (); appdomains_list [domain->domain_id] = NULL; diff --git a/mono/metadata/sre.c b/mono/metadata/sre.c index 63a9a99aaa3..691804c4f05 100644 --- a/mono/metadata/sre.c +++ b/mono/metadata/sre.c @@ -4267,7 +4267,7 @@ mono_reflection_type_handle_mono_type (MonoReflectionTypeHandle ref, MonoError * void mono_sre_generic_param_table_entry_free (GenericParamTableEntry *entry) { - mono_gc_deregister_root ((char*) &entry->gparam); + MONO_GC_UNREGISTER_ROOT_IF_MOVING (entry->gparam); g_free (entry); } -- 2.25.1