[sgen] Remove weak ref hashes.
authorJon Purdy <evincarofautumn@gmail.com>
Tue, 9 Dec 2014 22:24:13 +0000 (14:24 -0800)
committerJon Purdy <evincarofautumn@gmail.com>
Thu, 3 Sep 2015 23:01:09 +0000 (16:01 -0700)
These hashes were inefficiently duplicating the information in the
common GC handle data tables.

 * Make GC lock recursive. This must be reverted when the GC handles
   table is made lock-free.

 * Refactor handle allocation and handle data manipulation to avoid
   duplication and magic numbers.

 * Use GC handles in refqueue and monitors, because the dislink
   machinery no longer exists.

13 files changed:
mono/metadata/boehm-gc.c
mono/metadata/gc-internal.h
mono/metadata/gc.c
mono/metadata/monitor.c
mono/metadata/monitor.h
mono/metadata/sgen-bridge.c
mono/metadata/sgen-client-mono.h
mono/metadata/sgen-mono.c
mono/sgen/gc-internal-agnostic.h
mono/sgen/sgen-fin-weak-hash.c
mono/sgen/sgen-gc.c
mono/sgen/sgen-gc.h
mono/sgen/sgen-protocol-def.h

index 2fb0ec330f7288da57c42884fc8f6b4ced209171..52b701c3e50849086d126a04c509f0593857452e 100644 (file)
@@ -1462,4 +1462,9 @@ mono_gc_is_null (void)
        return FALSE;
 }
 
+gboolean
+mono_gc_object_older_than (MonoObject *object, int generation) {
+       return FALSE;
+}
+
 #endif /* no Boehm GC */
index caac7de930123d346f7e011ba10463ffbecf4972..0b977306b40910835a56a8172ae10388f88f1152 100644 (file)
@@ -11,6 +11,7 @@
 #define __MONO_METADATA_GC_INTERNAL_H__
 
 #include <glib.h>
+#include <mono/utils/gc_wrapper.h>
 #include <mono/metadata/object-internals.h>
 #include <mono/metadata/threads-types.h>
 #include <mono/sgen/gc-internal-agnostic.h>
@@ -375,5 +376,7 @@ extern gboolean log_finalizers;
 /* If set, do not run finalizers. */
 extern gboolean do_not_finalize;
 
+gboolean mono_gc_object_older_than (MonoObject *object, int generation);
+
 #endif /* __MONO_METADATA_GC_INTERNAL_H__ */
 
index 00018597956a45b08b6a6413bb03be17d0107d87..4d4998a2f5b11506117dcae3a586fab655cd9f29 100644 (file)
@@ -25,6 +25,7 @@
 #include <mono/metadata/threads-types.h>
 #include <mono/metadata/threadpool-ms.h>
 #include <mono/sgen/sgen-conf.h>
+#include <mono/sgen/sgen-gc.h>
 #include <mono/utils/mono-logger-internal.h>
 #include <mono/metadata/gc-internal.h>
 #include <mono/metadata/marshal.h> /* for mono_delegate_free_ftnptr () */
@@ -529,16 +530,17 @@ ves_icall_System_GC_get_ephemeron_tombstone (void)
 #define mono_allocator_lock() mono_mutex_lock (&allocator_section)
 #define mono_allocator_unlock() mono_mutex_unlock (&allocator_section)
 static mono_mutex_t allocator_section;
-static mono_mutex_t handle_section;
 
-typedef enum {
-       HANDLE_WEAK,
-       HANDLE_WEAK_TRACK,
-       HANDLE_NORMAL,
-       HANDLE_PINNED
-} HandleType;
+#ifndef HAVE_SGEN_GC
+static mono_mutex_t handle_section;
+#endif
 
-static HandleType mono_gchandle_get_type (guint32 gchandle);
+#define GC_HANDLE_TYPE_SHIFT (3)
+#define GC_HANDLE_TYPE_MASK ((1 << GC_HANDLE_TYPE_SHIFT) - 1)
+#define GC_HANDLE_TYPE(x) (((x) & GC_HANDLE_TYPE_MASK) - 1)
+#define GC_HANDLE_SLOT(x) ((x) >> GC_HANDLE_TYPE_SHIFT)
+#define GC_HANDLE_TYPE_IS_WEAK(x) ((x) <= HANDLE_WEAK_TRACK)
+#define GC_HANDLE_TAG(slot, type) (((slot) << GC_HANDLE_TYPE_SHIFT) | (((type) & GC_HANDLE_TYPE_MASK) + 1))
 
 MonoObject *
 ves_icall_System_GCHandle_GetTarget (guint32 handle)
@@ -583,7 +585,7 @@ ves_icall_System_GCHandle_GetAddrOfPinnedObject (guint32 handle)
 {
        MonoObject *obj;
 
-       if (mono_gchandle_get_type (handle) != HANDLE_PINNED)
+       if (GC_HANDLE_TYPE (handle) != HANDLE_PINNED)
                return (gpointer)-2;
        obj = mono_gchandle_get_target (handle);
        if (obj) {
@@ -614,28 +616,52 @@ typedef struct {
        gpointer *entries;
        guint32   size;
        guint8    type;
-       guint     slot_hint : 24; /* starting slot for search */
+       guint     slot_hint : 24; /* starting slot for search in bitmap */
        /* 2^16 appdomains should be enough for everyone (though I know I'll regret this in 20 years) */
        /* we alloc this only for weak refs, since we can get the domain directly in the other cases */
        guint16  *domain_ids;
 } HandleData;
 
+#define BITMAP_SIZE (sizeof (*((HandleData *)NULL)->bitmap) * CHAR_BIT)
+
+static inline gboolean
+slot_occupied (HandleData *handles, guint slot) {
+       return handles->bitmap [slot / BITMAP_SIZE] & (1 << (slot % BITMAP_SIZE));
+}
+
+static inline void
+vacate_slot (HandleData *handles, guint slot) {
+       handles->bitmap [slot / BITMAP_SIZE] &= ~(1 << (slot % BITMAP_SIZE));
+}
+
+static inline void
+occupy_slot (HandleData *handles, guint slot) {
+       handles->bitmap [slot / BITMAP_SIZE] |= 1 << (slot % BITMAP_SIZE);
+}
+
+#define EMPTY_HANDLE_DATA(type) {NULL, NULL, 0, (type), 0}
+
 /* weak and weak-track arrays will be allocated in malloc memory 
  */
 static HandleData gc_handles [] = {
-       {NULL, NULL, 0, HANDLE_WEAK, 0},
-       {NULL, NULL, 0, HANDLE_WEAK_TRACK, 0},
-       {NULL, NULL, 0, HANDLE_NORMAL, 0},
-       {NULL, NULL, 0, HANDLE_PINNED, 0}
+       EMPTY_HANDLE_DATA (HANDLE_WEAK),
+       EMPTY_HANDLE_DATA (HANDLE_WEAK_TRACK),
+       EMPTY_HANDLE_DATA (HANDLE_NORMAL),
+       EMPTY_HANDLE_DATA (HANDLE_PINNED)
 };
 
+
+#ifdef HAVE_SGEN_GC
+#define lock_handles(handles) sgen_gc_lock ()
+#define unlock_handles(handles) sgen_gc_unlock ()
+#else
 #define lock_handles(handles) do {     \
        MONO_TRY_BLOCKING;      \
        mono_mutex_lock (&handle_section);      \
        MONO_FINISH_TRY_BLOCKING;       \
 } while (0)
-
 #define unlock_handles(handles) mono_mutex_unlock (&handle_section)
+#endif
 
 static int
 find_first_unset (guint32 bitmap)
@@ -658,89 +684,109 @@ make_root_descr_all_refs (int numbits, gboolean pinned)
        return mono_gc_make_root_descr_all_refs (numbits);
 }
 
-static guint32
-alloc_handle (HandleData *handles, MonoObject *obj, gboolean track)
+static void
+handle_data_alloc_entries (HandleData *handles)
 {
-       gint slot, i;
-       guint32 res;
-       lock_handles (handles);
-       if (!handles->size) {
-               handles->size = 32;
-               if (handles->type > HANDLE_WEAK_TRACK) {
-                       handles->entries = mono_gc_alloc_fixed (sizeof (gpointer) * handles->size, make_root_descr_all_refs (handles->size, handles->type == HANDLE_PINNED), MONO_ROOT_SOURCE_GC_HANDLE, "gc handles table");
-               } else {
-                       handles->entries = g_malloc0 (sizeof (gpointer) * handles->size);
-                       handles->domain_ids = g_malloc0 (sizeof (guint16) * handles->size);
-               }
-               handles->bitmap = g_malloc0 (handles->size / 8);
-       }
-       i = -1;
-       for (slot = handles->slot_hint; slot < handles->size / 32; ++slot) {
-               if (handles->bitmap [slot] != 0xffffffff) {
-                       i = find_first_unset (handles->bitmap [slot]);
-                       handles->slot_hint = slot;
-                       break;
-               }
-       }
-       if (i == -1 && handles->slot_hint != 0) {
-               for (slot = 0; slot < handles->slot_hint; ++slot) {
-                       if (handles->bitmap [slot] != 0xffffffff) {
-                               i = find_first_unset (handles->bitmap [slot]);
-                               handles->slot_hint = slot;
-                               break;
-                       }
-               }
+       handles->size = 32;
+       if (GC_HANDLE_TYPE_IS_WEAK (handles->type)) {
+               handles->entries = g_malloc0 (sizeof (*handles->entries) * handles->size);
+               handles->domain_ids = g_malloc0 (sizeof (*handles->domain_ids) * handles->size);
+       } else {
+               handles->entries = mono_gc_alloc_fixed (sizeof (*handles->entries) * handles->size, make_root_descr_all_refs (handles->size, handles->type == HANDLE_PINNED), MONO_ROOT_SOURCE_GC_HANDLE, "gc handles table");
        }
-       if (i == -1) {
-               guint32 *new_bitmap;
-               guint32 new_size = handles->size * 2; /* always double: we memset to 0 based on this below */
-
-               /* resize and copy the bitmap */
-               new_bitmap = g_malloc0 (new_size / 8);
-               memcpy (new_bitmap, handles->bitmap, handles->size / 8);
-               g_free (handles->bitmap);
-               handles->bitmap = new_bitmap;
+       handles->bitmap = g_malloc0 (handles->size / CHAR_BIT);
+}
 
-               /* resize and copy the entries */
-               if (handles->type > HANDLE_WEAK_TRACK) {
-                       gpointer *entries;
+static gint
+handle_data_next_unset (HandleData *handles)
+{
+       gint slot;
+       for (slot = handles->slot_hint; slot < handles->size / BITMAP_SIZE; ++slot) {
+               if (handles->bitmap [slot] == 0xffffffff)
+                       continue;
+               handles->slot_hint = slot;
+               return find_first_unset (handles->bitmap [slot]);
+       }
+       return -1;
+}
 
-                       entries = mono_gc_alloc_fixed (sizeof (gpointer) * new_size, make_root_descr_all_refs (new_size, handles->type == HANDLE_PINNED), MONO_ROOT_SOURCE_GC_HANDLE, "gc handles table");
-                       mono_gc_memmove_aligned (entries, handles->entries, sizeof (gpointer) * handles->size);
+static gint
+handle_data_first_unset (HandleData *handles)
+{
+       gint slot;
+       for (slot = 0; slot < handles->slot_hint; ++slot) {
+               if (handles->bitmap [slot] == 0xffffffff)
+                       continue;
+               handles->slot_hint = slot;
+               return find_first_unset (handles->bitmap [slot]);
+       }
+       return -1;
+}
 
-                       mono_gc_free_fixed (handles->entries);
-                       handles->entries = entries;
-               } else {
-                       gpointer *entries;
-                       guint16 *domain_ids;
-                       domain_ids = g_malloc0 (sizeof (guint16) * new_size);
-                       entries = g_malloc0 (sizeof (gpointer) * new_size);
-                       memcpy (domain_ids, handles->domain_ids, sizeof (guint16) * handles->size);
-                       for (i = 0; i < handles->size; ++i) {
-                               MonoObject *obj = mono_gc_weak_link_get (&(handles->entries [i]));
-                               if (obj) {
-                                       mono_gc_weak_link_add (&(entries [i]), obj, track);
-                                       mono_gc_weak_link_remove (&(handles->entries [i]), track);
-                               } else {
-                                       g_assert (!handles->entries [i]);
-                               }
+/* Returns the index of the current slot in the bitmap. */
+static void
+handle_data_grow (HandleData *handles, gboolean track)
+{
+       guint32 *new_bitmap;
+       guint32 new_size = handles->size * 2; /* always double: we memset to 0 based on this below */
+
+       /* resize and copy the bitmap */
+       new_bitmap = g_malloc0 (new_size / CHAR_BIT);
+       memcpy (new_bitmap, handles->bitmap, handles->size / CHAR_BIT);
+       g_free (handles->bitmap);
+       handles->bitmap = new_bitmap;
+
+       /* resize and copy the entries */
+       if (GC_HANDLE_TYPE_IS_WEAK (handles->type)) {
+               gpointer *entries;
+               guint16 *domain_ids;
+               gint i;
+               domain_ids = g_malloc0 (sizeof (*handles->domain_ids) * new_size);
+               entries = g_malloc0 (sizeof (*handles->entries) * new_size);
+               memcpy (domain_ids, handles->domain_ids, sizeof (*handles->domain_ids) * handles->size);
+               for (i = 0; i < handles->size; ++i) {
+                       MonoObject *obj = mono_gc_weak_link_get (&(handles->entries [i]));
+                       if (obj) {
+                               mono_gc_weak_link_add (&(entries [i]), obj, track);
+                               mono_gc_weak_link_remove (&(handles->entries [i]), track);
+                       } else {
+                               g_assert (!handles->entries [i]);
                        }
-                       g_free (handles->entries);
-                       g_free (handles->domain_ids);
-                       handles->entries = entries;
-                       handles->domain_ids = domain_ids;
                }
+               g_free (handles->entries);
+               g_free (handles->domain_ids);
+               handles->entries = entries;
+               handles->domain_ids = domain_ids;
+       } else {
+               gpointer *entries;
+               entries = mono_gc_alloc_fixed (sizeof (*handles->entries) * new_size, make_root_descr_all_refs (new_size, handles->type == HANDLE_PINNED), MONO_ROOT_SOURCE_GC_HANDLE, "gc handles table");
+               mono_gc_memmove_aligned (entries, handles->entries, sizeof (*handles->entries) * handles->size);
+               mono_gc_free_fixed (handles->entries);
+               handles->entries = entries;
+       }
+       handles->slot_hint = handles->size / BITMAP_SIZE;
+       handles->size = new_size;
+}
 
-               /* set i and slot to the next free position */
+static guint32
+alloc_handle (HandleData *handles, MonoObject *obj, gboolean track)
+{
+       gint slot, i;
+       guint32 res;
+       lock_handles (handles);
+       if (!handles->size)
+               handle_data_alloc_entries (handles);
+       i = handle_data_next_unset (handles);
+       if (i == -1 && handles->slot_hint != 0)
+               i = handle_data_first_unset (handles);
+       if (i == -1) {
+               handle_data_grow (handles, track);
                i = 0;
-               slot = (handles->size + 1) / 32;
-               handles->slot_hint = handles->size + 1;
-               handles->size = new_size;
        }
-       handles->bitmap [slot] |= 1 << i;
-       slot = slot * 32 + i;
+       slot = handles->slot_hint * BITMAP_SIZE + i;
+       occupy_slot (handles, slot);
        handles->entries [slot] = NULL;
-       if (handles->type <= HANDLE_WEAK_TRACK) {
+       if (GC_HANDLE_TYPE_IS_WEAK (handles->type)) {
                /*FIXME, what to use when obj == null?*/
                handles->domain_ids [slot] = (obj ? mono_object_get_domain (obj) : mono_domain_get ())->domain_id;
                if (obj)
@@ -753,12 +799,28 @@ alloc_handle (HandleData *handles, MonoObject *obj, gboolean track)
        mono_perfcounters->gc_num_handles++;
 #endif
        unlock_handles (handles);
-       /*g_print ("allocated entry %d of type %d to object %p (in slot: %p)\n", slot, handles->type, obj, handles->entries [slot]);*/
-       res = (slot << 3) | (handles->type + 1);
+       res = GC_HANDLE_TAG (slot, handles->type);
        mono_profiler_gc_handle (MONO_PROFILER_GC_HANDLE_CREATED, handles->type, res, obj);
        return res;
 }
 
+void
+mono_gchandle_iterate (GCHandleType handle_type, int max_generation, gpointer callback(gpointer *, GCHandleType, gpointer), gpointer user)
+{
+       HandleData *handle_data = &gc_handles [handle_type];
+       size_t i;
+       lock_handles (handle_data);
+       for (i = 0; i < handle_data->size; ++i) {
+               gpointer *entry = &handle_data->entries [i];
+               /* Table must contain no garbage pointers. */
+               g_assert (*entry ? slot_occupied (handle_data, i) : TRUE);
+               if (!*entry || !slot_occupied (handle_data, i) || mono_gc_object_older_than (REVEAL_POINTER (*entry), max_generation))
+                       continue;
+               *entry = callback (entry, handle_type, user);
+       }
+       unlock_handles (handle_data);
+}
+
 /**
  * mono_gchandle_new:
  * @obj: managed object to get a handle for
@@ -809,14 +871,6 @@ mono_gchandle_new_weakref (MonoObject *obj, gboolean track_resurrection)
        return handle;
 }
 
-static HandleType
-mono_gchandle_get_type (guint32 gchandle)
-{
-       guint type = (gchandle & 7) - 1;
-
-       return type;
-}
-
 /**
  * mono_gchandle_get_target:
  * @gchandle: a GCHandle's handle.
@@ -830,15 +884,16 @@ mono_gchandle_get_type (guint32 gchandle)
 MonoObject*
 mono_gchandle_get_target (guint32 gchandle)
 {
-       guint slot = gchandle >> 3;
-       guint type = (gchandle & 7) - 1;
+       guint slot = GC_HANDLE_SLOT (gchandle);
+       guint type = GC_HANDLE_TYPE (gchandle);
        HandleData *handles = &gc_handles [type];
        MonoObject *obj = NULL;
-       if (type > 3)
+       if (type >= HANDLE_TYPE_MAX)
                return NULL;
+
        lock_handles (handles);
-       if (slot < handles->size && (handles->bitmap [slot / 32] & (1 << (slot % 32)))) {
-               if (handles->type <= HANDLE_WEAK_TRACK) {
+       if (slot < handles->size && slot_occupied (handles, slot)) {
+               if (GC_HANDLE_TYPE_IS_WEAK (handles->type)) {
                        obj = mono_gc_weak_link_get (&handles->entries [slot]);
                } else {
                        obj = handles->entries [slot];
@@ -854,15 +909,14 @@ mono_gchandle_get_target (guint32 gchandle)
 static void
 mono_gchandle_set_target (guint32 gchandle, MonoObject *obj)
 {
-       guint slot = gchandle >> 3;
-       guint type = (gchandle & 7) - 1;
+       guint slot = GC_HANDLE_SLOT (gchandle);
+       guint type = GC_HANDLE_TYPE (gchandle);
        HandleData *handles = &gc_handles [type];
 
-       if (type > 3)
-               return;
+       g_assert (type < HANDLE_TYPE_MAX);
        lock_handles (handles);
-       if (slot < handles->size && (handles->bitmap [slot / 32] & (1 << (slot % 32)))) {
-               if (handles->type <= HANDLE_WEAK_TRACK) {
+       if (slot < handles->size && slot_occupied (handles, slot)) {
+               if (GC_HANDLE_TYPE_IS_WEAK (handles->type)) {
                        if (handles->entries [slot])
                                mono_gc_weak_link_remove (&handles->entries [slot], handles->type == HANDLE_WEAK_TRACK);
                        if (obj)
@@ -889,15 +943,17 @@ mono_gchandle_set_target (guint32 gchandle, MonoObject *obj)
 gboolean
 mono_gchandle_is_in_domain (guint32 gchandle, MonoDomain *domain)
 {
-       guint slot = gchandle >> 3;
-       guint type = (gchandle & 7) - 1;
+       guint slot = GC_HANDLE_SLOT (gchandle);
+       guint type = GC_HANDLE_TYPE (gchandle);
        HandleData *handles = &gc_handles [type];
        gboolean result = FALSE;
-       if (type > 3)
+
+       if (type >= HANDLE_TYPE_MAX)
                return FALSE;
+
        lock_handles (handles);
-       if (slot < handles->size && (handles->bitmap [slot / 32] & (1 << (slot % 32)))) {
-               if (handles->type <= HANDLE_WEAK_TRACK) {
+       if (slot < handles->size && slot_occupied (handles, slot)) {
+               if (GC_HANDLE_TYPE_IS_WEAK (handles->type)) {
                        result = domain->domain_id == handles->domain_ids [slot];
                } else {
                        MonoObject *obj;
@@ -925,21 +981,21 @@ mono_gchandle_is_in_domain (guint32 gchandle, MonoDomain *domain)
 void
 mono_gchandle_free (guint32 gchandle)
 {
-       guint slot = gchandle >> 3;
-       guint type = (gchandle & 7) - 1;
+       guint slot = GC_HANDLE_SLOT (gchandle);
+       guint type = GC_HANDLE_TYPE (gchandle);
        HandleData *handles = &gc_handles [type];
-       if (type > 3)
+       if (type >= HANDLE_TYPE_MAX)
                return;
 
        lock_handles (handles);
-       if (slot < handles->size && (handles->bitmap [slot / 32] & (1 << (slot % 32)))) {
-               if (handles->type <= HANDLE_WEAK_TRACK) {
+       if (slot < handles->size && slot_occupied (handles, slot)) {
+               if (GC_HANDLE_TYPE_IS_WEAK (handles->type)) {
                        if (handles->entries [slot])
                                mono_gc_weak_link_remove (&handles->entries [slot], handles->type == HANDLE_WEAK_TRACK);
                } else {
                        handles->entries [slot] = NULL;
                }
-               handles->bitmap [slot / 32] &= ~(1 << (slot % 32));
+               vacate_slot (handles, slot);
        } else {
                /* print a warning? */
        }
@@ -963,22 +1019,22 @@ mono_gchandle_free_domain (MonoDomain *domain)
 {
        guint type;
 
-       for (type = 0; type < 3; ++type) {
+       for (type = HANDLE_TYPE_MIN; type < HANDLE_PINNED; ++type) {
                guint slot;
                HandleData *handles = &gc_handles [type];
                lock_handles (handles);
                for (slot = 0; slot < handles->size; ++slot) {
-                       if (!(handles->bitmap [slot / 32] & (1 << (slot % 32))))
+                       if (!slot_occupied (handles, slot))
                                continue;
-                       if (type <= HANDLE_WEAK_TRACK) {
+                       if (GC_HANDLE_TYPE_IS_WEAK (type)) {
                                if (domain->domain_id == handles->domain_ids [slot]) {
-                                       handles->bitmap [slot / 32] &= ~(1 << (slot % 32));
+                                       vacate_slot (handles, slot);
                                        if (handles->entries [slot])
                                                mono_gc_weak_link_remove (&handles->entries [slot], handles->type == HANDLE_WEAK_TRACK);
                                }
                        } else {
                                if (handles->entries [slot] && mono_object_domain (handles->entries [slot]) == domain) {
-                                       handles->bitmap [slot / 32] &= ~(1 << (slot % 32));
+                                       vacate_slot (handles, slot);
                                        handles->entries [slot] = NULL;
                                }
                        }
@@ -1174,7 +1230,9 @@ mono_gc_init_finalizer_thread (void)
 void
 mono_gc_init (void)
 {
+#ifndef HAVE_SGEN_GC
        mono_mutex_init_recursive (&handle_section);
+#endif
        mono_mutex_init_recursive (&allocator_section);
 
        mono_mutex_init_recursive (&finalizer_mutex);
@@ -1285,6 +1343,10 @@ mono_gc_cleanup (void)
 
        mono_reference_queue_cleanup ();
 
+#ifndef HAVE_SGEN_GC
+       mono_mutex_destroy (&handle_section);
+#endif
+
        mono_mutex_destroy (&allocator_section);
        mono_mutex_destroy (&finalizer_mutex);
        mono_mutex_destroy (&reference_queue_mutex);
@@ -1298,7 +1360,9 @@ mono_gc_cleanup (void)
 void
 mono_gc_mutex_cleanup (void)
 {
+#ifndef HAVE_SGEN_GC
        mono_mutex_destroy (&handle_section);
+#endif
 }
 
 gboolean
@@ -1377,13 +1441,8 @@ reference_queue_proccess (MonoReferenceQueue *queue)
        RefQueueEntry **iter = &queue->queue;
        RefQueueEntry *entry;
        while ((entry = *iter)) {
-#ifdef HAVE_SGEN_GC
-               if (queue->should_be_deleted || !mono_gc_weak_link_get (&entry->dis_link)) {
-                       mono_gc_weak_link_remove (&entry->dis_link, TRUE);
-#else
                if (queue->should_be_deleted || !mono_gchandle_get_target (entry->gchandle)) {
                        mono_gchandle_free ((guint32)entry->gchandle);
-#endif
                        ref_list_remove_element (iter, entry);
                        queue->callback (entry->user_data);
                        g_free (entry);
@@ -1438,11 +1497,7 @@ reference_queue_clear_for_domain (MonoDomain *domain)
                RefQueueEntry *entry;
                while ((entry = *iter)) {
                        if (entry->domain == domain) {
-#ifdef HAVE_SGEN_GC
-                               mono_gc_weak_link_remove (&entry->dis_link, TRUE);
-#else
                                mono_gchandle_free ((guint32)entry->gchandle);
-#endif
                                ref_list_remove_element (iter, entry);
                                queue->callback (entry->user_data);
                                g_free (entry);
@@ -1506,12 +1561,8 @@ mono_gc_reference_queue_add (MonoReferenceQueue *queue, MonoObject *obj, void *u
        entry->user_data = user_data;
        entry->domain = mono_object_domain (obj);
 
-#ifdef HAVE_SGEN_GC
-       mono_gc_weak_link_add (&entry->dis_link, obj, TRUE);
-#else
        entry->gchandle = mono_gchandle_new_weakref (obj, TRUE);
        mono_object_register_finalizer (obj);
-#endif
 
        ref_list_push (&queue->queue, entry);
        return TRUE;
index 0d9001be1a05514840d263c456affd595d3765e7..151c1d382c91033269361ce8ff1fcdbb2da617f2 100644 (file)
@@ -331,7 +331,7 @@ mono_locks_dump (gboolean include_untaken)
                                        to_recycle++;
                        } else {
                                if (!monitor_is_on_freelist (mon->data)) {
-                                       MonoObject *holder = mono_gc_weak_link_get (&mon->data);
+                                       MonoObject *holder = (MonoObject *)mono_gchandle_get_target ((guint32)mon->data);
                                        if (mon_status_get_owner (mon->status)) {
                                                g_print ("Lock %p in object %p held by thread %d, nest level: %d\n",
                                                        mon, holder, mon_status_get_owner (mon->status), mon->nest);
@@ -387,7 +387,7 @@ mon_new (gsize id)
                new = NULL;
                for (marray = monitor_allocated; marray; marray = marray->next) {
                        for (i = 0; i < marray->num_monitors; ++i) {
-                               if (marray->monitors [i].data == NULL) {
+                               if (mono_gchandle_get_target ((guint32)marray->monitors [i].data) == NULL) {
                                        new = &marray->monitors [i];
                                        if (new->wait_list) {
                                                /* Orphaned events left by aborted threads */
@@ -397,7 +397,7 @@ mon_new (gsize id)
                                                        new->wait_list = g_slist_remove (new->wait_list, new->wait_list->data);
                                                }
                                        }
-                                       mono_gc_weak_link_remove (&new->data, TRUE);
+                                       mono_gchandle_free ((guint32)new->data);
                                        new->data = monitor_freelist;
                                        monitor_freelist = new;
                                }
@@ -454,7 +454,7 @@ alloc_mon (MonoObject *obj, gint32 id)
 
        mono_monitor_allocator_lock ();
        mon = mon_new (id);
-       mono_gc_weak_link_add (&mon->data, obj, TRUE);
+       mon->data = (void *)(size_t)mono_gchandle_new_weakref (obj, TRUE);
        mono_monitor_allocator_unlock ();
 
        return mon;
@@ -465,7 +465,7 @@ static void
 discard_mon (MonoThreadsSync *mon)
 {
        mono_monitor_allocator_lock ();
-       mono_gc_weak_link_remove (&mon->data, TRUE);
+       mono_gchandle_free ((guint32)mon->data);
        mon_finalize (mon);
        mono_monitor_allocator_unlock ();
 }
@@ -1036,8 +1036,8 @@ mono_monitor_exit (MonoObject *obj)
                mono_monitor_exit_flat (obj, lw);
 }
 
-void**
-mono_monitor_get_object_monitor_weak_link (MonoObject *object)
+guint32
+mono_monitor_get_object_monitor_gchandle (MonoObject *object)
 {
        LockWord lw;
 
@@ -1045,10 +1045,9 @@ mono_monitor_get_object_monitor_weak_link (MonoObject *object)
 
        if (lock_word_is_inflated (lw)) {
                MonoThreadsSync *mon = lock_word_get_inflated_lock (lw);
-               if (mon->data)
-                       return &mon->data;
+               return (guint32)mon->data;
        }
-       return NULL;
+       return 0;
 }
 
 /*
index cc00f2044dc08d8638a7e1b0dfe4b4505ed18db1..bd796254034eac6f4fee232c63554231442536c3 100644 (file)
@@ -106,7 +106,7 @@ MONO_API void mono_locks_dump (gboolean include_untaken);
 void mono_monitor_init (void);
 void mono_monitor_cleanup (void);
 
-void** mono_monitor_get_object_monitor_weak_link (MonoObject *object);
+guint32 mono_monitor_get_object_monitor_gchandle (MonoObject *object);
 
 void mono_monitor_threads_sync_members_offset (int *status_offset, int *nest_offset);
 #define MONO_THREADS_SYNC_MEMBER_OFFSET(o)     ((o)>>8)
index 47f4f94db5c2fd6c7faaaf703771972a1415fc76..3f2992dbb047b37f20099d6e92f611f915bf8d84 100644 (file)
@@ -179,9 +179,12 @@ null_weak_links_to_dead_objects (SgenBridgeProcessor *processor, int generation)
        }
 
        /* Null weak links to dead objects. */
-       sgen_null_links_if (is_bridge_object_dead, &alive_hash, GENERATION_NURSERY);
-       if (generation == GENERATION_OLD)
-               sgen_null_links_if (is_bridge_object_dead, &alive_hash, GENERATION_OLD);
+       sgen_null_links_if (is_bridge_object_dead, &alive_hash, GENERATION_NURSERY, FALSE);
+       sgen_null_links_if (is_bridge_object_dead, &alive_hash, GENERATION_NURSERY, TRUE);
+       if (generation == GENERATION_OLD) {
+               sgen_null_links_if (is_bridge_object_dead, &alive_hash, GENERATION_OLD, FALSE);
+               sgen_null_links_if (is_bridge_object_dead, &alive_hash, GENERATION_OLD, TRUE);
+       }
 
        sgen_hash_table_clean (&alive_hash);
 }
index ede6e48ba408d971d305f1b682051554faea5561..7b4fdc66d7adbc322ed765e8f87c121a3f1f28a1 100644 (file)
@@ -571,7 +571,7 @@ sgen_client_binary_protocol_cleanup (gpointer ptr, gpointer vtable, size_t size)
 }
 
 static void G_GNUC_UNUSED
-sgen_client_binary_protocol_dislink_update (gpointer link, gpointer obj, gboolean track, gboolean staged)
+sgen_client_binary_protocol_dislink_update (gpointer link, gpointer obj, gboolean track)
 {
 #ifdef ENABLE_DTRACE
        if (MONO_GC_WEAK_UPDATE_ENABLED ()) {
index 4e388d1557a28e2e0be4fb58ba73089c4d660627..b946b36c699f5746b830913894a3828650aa59a3 100644 (file)
@@ -784,9 +784,9 @@ clear_domain_process_object (GCObject *obj, MonoDomain *domain)
        remove = need_remove_object_for_domain (obj, domain);
 
        if (remove && obj->synchronisation) {
-               void **dislink = mono_monitor_get_object_monitor_weak_link (obj);
+               guint32 dislink = mono_monitor_get_object_monitor_gchandle (obj);
                if (dislink)
-                       sgen_register_disappearing_link (NULL, dislink, FALSE, TRUE);
+                       mono_gchandle_free (dislink);
        }
 
        return remove;
@@ -863,8 +863,10 @@ mono_gc_clear_domain (MonoDomain * domain)
        to memory returned to the OS.*/
        null_ephemerons_for_domain (domain);
 
-       for (i = GENERATION_NURSERY; i < GENERATION_MAX; ++i)
-               sgen_null_links_if (object_in_domain_predicate, domain, i);
+       for (i = GENERATION_NURSERY; i < GENERATION_MAX; ++i) {
+               sgen_null_links_if (object_in_domain_predicate, domain, i, FALSE);
+               sgen_null_links_if (object_in_domain_predicate, domain, i, TRUE);
+       }
 
        for (i = GENERATION_NURSERY; i < GENERATION_MAX; ++i)
                sgen_remove_finalizers_if (object_in_domain_predicate, domain, i);
@@ -2571,13 +2573,15 @@ mono_gc_get_los_limit (void)
 void
 mono_gc_weak_link_add (void **link_addr, MonoObject *obj, gboolean track)
 {
-       sgen_register_disappearing_link (obj, link_addr, track, FALSE);
+       binary_protocol_dislink_add ((gpointer)link_addr, obj, track);
+       *link_addr = (void*)HIDE_POINTER (obj);
 }
 
 void
 mono_gc_weak_link_remove (void **link_addr, gboolean track)
 {
-       sgen_register_disappearing_link (NULL, link_addr, track, FALSE);
+       binary_protocol_dislink_remove ((gpointer)link_addr, track);
+       *link_addr = NULL;
 }
 
 MonoObject*
@@ -2586,6 +2590,12 @@ mono_gc_weak_link_get (void **link_addr)
        return sgen_weak_link_get (link_addr);
 }
 
+gboolean
+mono_gc_object_older_than (MonoObject *object, int generation)
+{
+       return generation == GENERATION_NURSERY && !sgen_ptr_in_nursery (object);
+}
+
 gboolean
 mono_gc_set_allow_synchronous_major (gboolean flag)
 {
index b7e4b6708c0681b3dcad2d0d611912c9e40d252c..ef85b74d36c67b94e1568fa140526a8faeed7793 100644 (file)
 #include "mono/sgen/sgen-conf.h"
 #endif
 
+#ifndef HIDE_POINTER
+#define HIDE_POINTER(p) ((gpointer)~(size_t)(p))
+#endif
+
+#ifndef REVEAL_POINTER
+#define REVEAL_POINTER(p) ((gpointer)~(size_t)(p))
+#endif
+
+typedef enum {
+       HANDLE_TYPE_MIN = 0,
+       HANDLE_WEAK = HANDLE_TYPE_MIN,
+       HANDLE_WEAK_TRACK,
+       HANDLE_NORMAL,
+       HANDLE_PINNED,
+       HANDLE_TYPE_MAX
+} GCHandleType;
+
+void mono_gchandle_iterate (GCHandleType handle_type, int max_generation, gpointer callback(gpointer *, GCHandleType, gpointer), gpointer user);
+
 typedef struct {
        guint minor_gc_count;
        guint major_gc_count;
index a0994b9a1be1c9d03f2fd0285c0713ab514f4e41..5bf77c4fde3972a29581dad5846d6a264c7a8ec5 100644 (file)
@@ -32,6 +32,7 @@
 #include "mono/sgen/sgen-protocol.h"
 #include "mono/sgen/sgen-pointer-queue.h"
 #include "mono/sgen/sgen-client.h"
+#include "mono/sgen/gc-internal-agnostic.h"
 #include "mono/utils/mono-membar.h"
 
 #define ptr_in_nursery sgen_ptr_in_nursery
@@ -629,147 +630,62 @@ sgen_gather_finalizers_if (SgenObjectPredicateFunc predicate, void *user_data, G
        return result;
 }
 
-static SgenHashTable minor_disappearing_link_hash = SGEN_HASH_TABLE_INIT (INTERNAL_MEM_DISLINK_TABLE, INTERNAL_MEM_DISLINK, 0, sgen_aligned_addr_hash, NULL);
-static SgenHashTable major_disappearing_link_hash = SGEN_HASH_TABLE_INIT (INTERNAL_MEM_DISLINK_TABLE, INTERNAL_MEM_DISLINK, 0, sgen_aligned_addr_hash, NULL);
-
-static SgenHashTable*
-get_dislink_hash_table (int generation)
-{
-       switch (generation) {
-       case GENERATION_NURSERY: return &minor_disappearing_link_hash;
-       case GENERATION_OLD: return &major_disappearing_link_hash;
-       default: g_assert_not_reached ();
-       }
-}
-
-/* LOCKING: assumes the GC lock is held */
-static void
-add_or_remove_disappearing_link (GCObject *obj, void **link, int generation)
+/*
+ * Returns whether to remove the link from its hash.
+ */
+static gpointer
+null_link_if_necessary (gpointer *hidden_entry, GCHandleType handle_type, gpointer user)
 {
-       SgenHashTable *hash_table = get_dislink_hash_table (generation);
-
-       if (!obj) {
-               if (sgen_hash_table_remove (hash_table, link, NULL)) {
-                       SGEN_LOG (5, "Removed dislink %p (%d) from %s table",
-                                       link, hash_table->num_entries, sgen_generation_name (generation));
-               }
-               return;
+       ScanCopyContext *ctx = (ScanCopyContext *)user;
+       gpointer entry = REVEAL_POINTER (*hidden_entry);
+       char *copy = entry;
+       gboolean entry_in_nursery = ptr_in_nursery (entry);
+       if (sgen_get_current_collection_generation () == GENERATION_NURSERY && !entry_in_nursery)
+               return *hidden_entry;
+       /* Clear link if object is ready for finalization. */
+       if (sgen_gc_is_object_ready_for_finalization (entry)) {
+               return NULL;
        }
-
-       sgen_hash_table_replace (hash_table, link, NULL, NULL);
-       SGEN_LOG (5, "Added dislink for object: %p (%s) at %p to %s table",
-                       obj, sgen_client_vtable_get_name (SGEN_LOAD_VTABLE_UNCHECKED (obj)), link, sgen_generation_name (generation));
+       ctx->ops->copy_or_mark_object ((void **)&copy, ctx->queue);
+       g_assert (copy);
+       /* Update pointer if it's moved. */
+       binary_protocol_dislink_update (hidden_entry, copy, handle_type == HANDLE_WEAK_TRACK);
+       return HIDE_POINTER (copy);
 }
 
 /* LOCKING: requires that the GC lock is held */
 void
-sgen_null_link_in_range (int generation, gboolean before_finalization, ScanCopyContext ctx)
+sgen_null_link_in_range (int generation, gboolean before_finalization, ScanCopyContext ctx, gboolean track)
 {
-       CopyOrMarkObjectFunc copy_func = ctx.ops->copy_or_mark_object;
-       GrayQueue *queue = ctx.queue;
-       void **link;
-       gpointer dummy G_GNUC_UNUSED;
-       SgenHashTable *hash = get_dislink_hash_table (generation);
-
-       SGEN_HASH_TABLE_FOREACH (hash, link, dummy) {
-               GCObject *object;
-               gboolean track;
-
-               /*
-               We null a weak link before unregistering it, so it's possible that a thread is
-               suspended right in between setting the content to null and staging the unregister.
-
-               The rest of this code cannot handle null links as DISLINK_OBJECT (NULL) produces an invalid address.
-
-               We should simply skip the entry as the staged removal will take place during the next GC.
-               */
-               if (!*link) {
-                       SGEN_LOG (5, "Dislink %p was externally nullified", link);
-                       continue;
-               }
+       mono_gchandle_iterate (track ? HANDLE_WEAK_TRACK : HANDLE_WEAK, generation, null_link_if_necessary, &ctx);
+}
 
-               track = DISLINK_TRACK (link);
-               /*
-                * Tracked references are processed after
-                * finalization handling whereas standard weak
-                * references are processed before.  If an
-                * object is still not marked after finalization
-                * handling it means that it either doesn't have
-                * a finalizer or the finalizer has already run,
-                * so we must null a tracking reference.
-                */
-               if (track != before_finalization) {
-                       object = DISLINK_OBJECT (link);
-                       /*
-                       We should guard against a null object been hidden. This can sometimes happen.
-                       */
-                       if (!object) {
-                               SGEN_LOG (5, "Dislink %p with a hidden null object", link);
-                               continue;
-                       }
+typedef struct {
+       SgenObjectPredicateFunc predicate;
+       gpointer data;
+} WeakLinkAlivePredicateClosure;
 
-                       if (!major_collector.is_object_live (object)) {
-                               if (sgen_gc_is_object_ready_for_finalization (object)) {
-                                       *link = NULL;
-                                       binary_protocol_dislink_update (link, NULL, 0, 0);
-                                       SGEN_LOG (5, "Dislink nullified at %p to GCed object %p", link, object);
-                                       SGEN_HASH_TABLE_FOREACH_REMOVE (TRUE);
-                                       continue;
-                               } else {
-                                       GCObject *copy = object;
-                                       copy_func (&copy, queue);
-
-                                       /* Update pointer if it's moved.  If the object
-                                        * has been moved out of the nursery, we need to
-                                        * remove the link from the minor hash table to
-                                        * the major one.
-                                        *
-                                        * FIXME: what if an object is moved earlier?
-                                        */
-
-                                       if (hash == &minor_disappearing_link_hash && !ptr_in_nursery (copy)) {
-                                               SGEN_HASH_TABLE_FOREACH_REMOVE (TRUE);
-
-                                               g_assert (copy);
-                                               *link = HIDE_POINTER (copy, track);
-                                               add_or_remove_disappearing_link (copy, link, GENERATION_OLD);
-                                               binary_protocol_dislink_update (link, copy, track, 0);
-
-                                               SGEN_LOG (5, "Upgraded dislink at %p to major because object %p moved to %p", link, object, copy);
-
-                                               continue;
-                                       } else {
-                                               *link = HIDE_POINTER (copy, track);
-                                               binary_protocol_dislink_update (link, copy, track, 0);
-                                               SGEN_LOG (5, "Updated dislink at %p to %p", link, DISLINK_OBJECT (link));
-                                       }
-                               }
-                       }
-               }
-       } SGEN_HASH_TABLE_FOREACH_END;
+static gpointer
+null_link_if (gpointer *hidden_entry, GCHandleType handle_type, gpointer user)
+{
+       /* Strictly speaking, function pointers are not guaranteed to have the same size as data pointers. */
+       WeakLinkAlivePredicateClosure *closure = (WeakLinkAlivePredicateClosure *)user;
+       gpointer entry = REVEAL_POINTER (*hidden_entry);
+       if (!entry)
+               return NULL;
+       if (closure->predicate ((MonoObject*)entry, closure->data)) {
+               binary_protocol_dislink_update (hidden_entry, NULL, 0);
+               return NULL;
+       }
+       return *hidden_entry;
 }
 
 /* LOCKING: requires that the GC lock is held */
 void
-sgen_null_links_if (SgenObjectPredicateFunc predicate, void *data, int generation)
+sgen_null_links_if (SgenObjectPredicateFunc predicate, void *data, int generation, gboolean track)
 {
-       void **link;
-       gpointer dummy G_GNUC_UNUSED;
-       SgenHashTable *hash = get_dislink_hash_table (generation);
-       SGEN_HASH_TABLE_FOREACH (hash, link, dummy) {
-               char *object = DISLINK_OBJECT (link);
-
-               if (!*link)
-                       continue;
-
-               if (predicate ((GCObject*)object, data)) {
-                       *link = NULL;
-                       binary_protocol_dislink_update (link, NULL, 0, 0);
-                       SGEN_LOG (5, "Dislink nullified by predicate at %p to GCed object %p", link, object);
-                       SGEN_HASH_TABLE_FOREACH_REMOVE (FALSE /* TRUE */);
-                       continue;
-               }
-       } SGEN_HASH_TABLE_FOREACH_END;
+       WeakLinkAlivePredicateClosure closure = { predicate, data };
+       mono_gchandle_iterate (track ? HANDLE_WEAK_TRACK : HANDLE_WEAK, generation, null_link_if, &closure);
 }
 
 void
@@ -789,70 +705,15 @@ sgen_remove_finalizers_if (SgenObjectPredicateFunc predicate, void *user_data, i
        } SGEN_HASH_TABLE_FOREACH_END;  
 }
 
-/* LOCKING: requires that the GC lock is held */
-static void
-process_dislink_stage_entry (GCObject *obj, void *_link, int index)
-{
-       void **link = _link;
-
-       if (index >= 0)
-               binary_protocol_dislink_process_staged (link, obj, index);
-
-       add_or_remove_disappearing_link (NULL, link, GENERATION_NURSERY);
-       add_or_remove_disappearing_link (NULL, link, GENERATION_OLD);
-       if (obj) {
-               if (ptr_in_nursery (obj))
-                       add_or_remove_disappearing_link (obj, link, GENERATION_NURSERY);
-               else
-                       add_or_remove_disappearing_link (obj, link, GENERATION_OLD);
-       }
-}
-
 #define NUM_DISLINK_STAGE_ENTRIES      1024
 
 static volatile gint32 next_dislink_stage_entry = 0;
-static StageEntry dislink_stage_entries [NUM_DISLINK_STAGE_ENTRIES];
 
 /* LOCKING: requires that the GC lock is held */
 void
 sgen_process_dislink_stage_entries (void)
 {
        lock_stage_for_processing (&next_dislink_stage_entry);
-       process_stage_entries (NUM_DISLINK_STAGE_ENTRIES, &next_dislink_stage_entry, dislink_stage_entries, process_dislink_stage_entry);
-}
-
-void
-sgen_register_disappearing_link (GCObject *obj, void **link, gboolean track, gboolean in_gc)
-{
-       if (obj)
-               *link = HIDE_POINTER (obj, track);
-       else
-               *link = NULL;
-
-#if 1
-       if (in_gc) {
-               binary_protocol_dislink_update (link, obj, track, 0);
-               process_dislink_stage_entry (obj, link, -1);
-       } else {
-               int index;
-               binary_protocol_dislink_update (link, obj, track, 1);
-               while ((index = add_stage_entry (NUM_DISLINK_STAGE_ENTRIES, &next_dislink_stage_entry, dislink_stage_entries, obj, link)) == -1) {
-                       if (try_lock_stage_for_processing (NUM_DISLINK_STAGE_ENTRIES, &next_dislink_stage_entry)) {
-                               LOCK_GC;
-                               process_stage_entries (NUM_DISLINK_STAGE_ENTRIES, &next_dislink_stage_entry, dislink_stage_entries, process_dislink_stage_entry);
-                               UNLOCK_GC;
-                       }
-               }
-               binary_protocol_dislink_update_staged (link, obj, track, index);
-       }
-#else
-       if (!in_gc)
-               LOCK_GC;
-       binary_protocol_dislink_update (link, obj, track, 0);
-       process_dislink_stage_entry (obj, link, -1);
-       if (!in_gc)
-               UNLOCK_GC;
-#endif
 }
 
 void
index f00706d9772a308fb4db9a70b29c10d08a5acbc5..382b259e711c65e3dd65b95befcee7b7c9e47505 100644 (file)
@@ -1138,9 +1138,9 @@ finish_gray_stack (int generation, ScanCopyContext ctx)
        We must clear weak links that don't track resurrection before processing object ready for
        finalization so they can be cleared before that.
        */
-       sgen_null_link_in_range (generation, TRUE, ctx);
+       sgen_null_link_in_range (generation, TRUE, ctx, FALSE);
        if (generation == GENERATION_OLD)
-               sgen_null_link_in_range (GENERATION_NURSERY, TRUE, ctx);
+               sgen_null_link_in_range (GENERATION_NURSERY, TRUE, ctx, FALSE);
 
 
        /* walk the finalization queue and move also the objects that need to be
@@ -1187,9 +1187,9 @@ finish_gray_stack (int generation, ScanCopyContext ctx)
         */
        g_assert (sgen_gray_object_queue_is_empty (queue));
        for (;;) {
-               sgen_null_link_in_range (generation, FALSE, ctx);
+               sgen_null_link_in_range (generation, FALSE, ctx, TRUE);
                if (generation == GENERATION_OLD)
-                       sgen_null_link_in_range (GENERATION_NURSERY, FALSE, ctx);
+                       sgen_null_link_in_range (GENERATION_NURSERY, FALSE, ctx, TRUE);
                if (sgen_gray_object_queue_is_empty (queue))
                        break;
                sgen_drain_gray_stack (-1, ctx);
@@ -2873,7 +2873,7 @@ sgen_gc_init (void)
        mono_thread_smr_init ();
 #endif
 
-       LOCK_INIT (gc_mutex);
+       mono_mutex_init_recursive (&gc_mutex);
 
        gc_debug_file = stderr;
 
index 5594db16c7fe25f566c6f76037a29ef6af6b975d..327d47f08c6964216cb6f70fc0cea6658e48f6fd 100644 (file)
@@ -172,14 +172,6 @@ sgen_aligned_addr_hash (gconstpointer ptr)
        return GPOINTER_TO_UINT (ptr) >> 3;
 }
 
-/*
- * The link pointer is hidden by negating each bit.  We use the lowest
- * bit of the link (before negation) to store whether it needs
- * resurrection tracking.
- */
-#define HIDE_POINTER(p,t)      ((gpointer)(~((size_t)(p)|((t)?1:0))))
-#define REVEAL_POINTER(p)      ((gpointer)((~(size_t)(p))&~3L))
-
 #define SGEN_PTR_IN_NURSERY(p,bits,start,end)  (((mword)(p) & ~((1 << (bits)) - 1)) == (mword)(start))
 
 #ifdef USER_CONFIG
@@ -786,7 +778,7 @@ void sgen_collect_bridge_objects (int generation, ScanCopyContext ctx);
 
 typedef gboolean (*SgenObjectPredicateFunc) (GCObject *obj, void *user_data);
 
-void sgen_null_links_if (SgenObjectPredicateFunc predicate, void *data, int generation);
+void sgen_null_links_if (SgenObjectPredicateFunc predicate, void *data, int generation, gboolean track);
 
 gboolean sgen_gc_is_object_ready_for_finalization (GCObject *object);
 void sgen_gc_lock (void);
@@ -796,7 +788,7 @@ void sgen_queue_finalization_entry (GCObject *obj);
 const char* sgen_generation_name (int generation);
 
 void sgen_finalize_in_range (int generation, ScanCopyContext ctx);
-void sgen_null_link_in_range (int generation, gboolean before_finalization, ScanCopyContext ctx);
+void sgen_null_link_in_range (int generation, gboolean before_finalization, ScanCopyContext ctx, gboolean track);
 void sgen_process_fin_stage_entries (void);
 gboolean sgen_have_pending_finalizers (void);
 void sgen_object_register_for_finalization (GCObject *obj, void *user_data);
index ca1e053e64ba01fef649be738e5875dc384f8320..fec52341131225e369ba0efda9646efb7decb152 100644 (file)
@@ -307,24 +307,24 @@ MATCH_INDEX (BINARY_PROTOCOL_MATCH)
 IS_VTABLE_MATCH (FALSE)
 END_PROTOCOL_ENTRY
 
-BEGIN_PROTOCOL_ENTRY_HEAVY4 (binary_protocol_dislink_update, TYPE_POINTER, link, TYPE_POINTER, obj, TYPE_BOOL, track, TYPE_BOOL, staged)
-CUSTOM_PRINT(entry->obj ? printf ("link %p obj %p staged %d track %d", entry->link, entry->obj, entry->staged, entry->track) : printf ("link %p obj %p staged %d", entry->link, entry->obj, entry->staged))
+BEGIN_PROTOCOL_ENTRY_HEAVY3 (binary_protocol_dislink_add, TYPE_POINTER, link, TYPE_POINTER, obj, TYPE_BOOL, track)
+DEFAULT_PRINT ()
 IS_ALWAYS_MATCH (FALSE)
 MATCH_INDEX (ptr == entry->link ? 0 : ptr == entry->obj ? 1 : BINARY_PROTOCOL_NO_MATCH)
 IS_VTABLE_MATCH (FALSE)
 END_PROTOCOL_ENTRY_HEAVY
 
-BEGIN_PROTOCOL_ENTRY_HEAVY4 (binary_protocol_dislink_update_staged, TYPE_POINTER, link, TYPE_POINTER, obj, TYPE_BOOL, track, TYPE_INT, index)
-CUSTOM_PRINT(entry->obj ? printf ("link %p obj %p index %d track %d", entry->link, entry->obj, entry->index, entry->track) : printf ("link %p obj %p index %d", entry->link, entry->obj, entry->index))
+BEGIN_PROTOCOL_ENTRY_HEAVY3 (binary_protocol_dislink_update, TYPE_POINTER, link, TYPE_POINTER, obj, TYPE_BOOL, track)
+CUSTOM_PRINT(entry->obj ? printf ("link %p obj %p track %d", entry->link, entry->obj, entry->track) : printf ("link %p obj %p", entry->link, entry->obj))
 IS_ALWAYS_MATCH (FALSE)
 MATCH_INDEX (ptr == entry->link ? 0 : ptr == entry->obj ? 1 : BINARY_PROTOCOL_NO_MATCH)
 IS_VTABLE_MATCH (FALSE)
 END_PROTOCOL_ENTRY_HEAVY
 
-BEGIN_PROTOCOL_ENTRY_HEAVY3 (binary_protocol_dislink_process_staged, TYPE_POINTER, link, TYPE_POINTER, obj, TYPE_INT, index)
+BEGIN_PROTOCOL_ENTRY_HEAVY2 (binary_protocol_dislink_remove, TYPE_POINTER, link, TYPE_INT, track)
 DEFAULT_PRINT ()
 IS_ALWAYS_MATCH (FALSE)
-MATCH_INDEX (ptr == entry->link ? 0 : ptr == entry->obj ? 1 : BINARY_PROTOCOL_NO_MATCH)
+MATCH_INDEX (ptr == entry->link ? 0 : BINARY_PROTOCOL_NO_MATCH)
 IS_VTABLE_MATCH (FALSE)
 END_PROTOCOL_ENTRY_HEAVY