Implement GC roots ourselves in Boehm rather than relying on their concept of roots...
authorJonathan Chambers <joncham@gmail.com>
Tue, 27 Jun 2017 04:45:26 +0000 (00:45 -0400)
committerAleksey Kliger (λgeek) <akliger@gmail.com>
Wed, 28 Jun 2017 18:43:38 +0000 (14:43 -0400)
mono/metadata/boehm-gc.c
mono/metadata/domain.c
mono/metadata/sre.c

index abbea870830954a4ac2f069f45a55ed69ae0c506..50ff079d1e2808a8829b893adfca1d992d765ce8 100644 (file)
@@ -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
index 1d353b1da070a4857d2e7a883eaa61ff73a88d38..16dc31752dde7b1879bc52d9a1042f45f6053aaf 100644 (file)
@@ -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;
index 63a9a99aaa3762e294aa6056cdf59769f25469ff..691804c4f051dc2d279814e3bb6e2d361759d811 100644 (file)
@@ -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);
 }