From 1c6d1f6d17c572533740f62bb122e693ee75a091 Mon Sep 17 00:00:00 2001 From: Mark Probst Date: Thu, 30 Apr 2015 11:52:01 -0700 Subject: [PATCH] [sgen] Pass hidden entry to GC handle iteration callback. --- mono/sgen/sgen-fin-weak-hash.c | 74 +++++++++++++++++++++------------- mono/sgen/sgen-gc.h | 1 - 2 files changed, 45 insertions(+), 30 deletions(-) diff --git a/mono/sgen/sgen-fin-weak-hash.c b/mono/sgen/sgen-fin-weak-hash.c index 0e2fc8d12bd..72b532b3f53 100644 --- a/mono/sgen/sgen-fin-weak-hash.c +++ b/mono/sgen/sgen-fin-weak-hash.c @@ -879,8 +879,8 @@ object_older_than (GCObject *object, int generation) * Maps a function over all GC handles. * This assumes that the world is stopped! */ -void -sgen_gchandle_iterate (GCHandleType handle_type, int max_generation, gpointer callback(GCObject*, GCHandleType, gpointer), gpointer user) +static void +sgen_gchandle_iterate (GCHandleType handle_type, int max_generation, gpointer callback(gpointer, GCHandleType, int, gpointer), gpointer user) { HandleData *handle_data = gc_handles_for_type (handle_type); size_t bucket, offset; @@ -893,22 +893,19 @@ sgen_gchandle_iterate (GCHandleType handle_type, int max_generation, gpointer ca volatile gpointer *entries = handle_data->entries [bucket]; for (offset = 0; offset < bucket_size (bucket); ++offset) { gpointer hidden = entries [offset]; - gpointer revealed; gpointer result; /* Table must contain no garbage pointers. */ gboolean occupied = MONO_GC_HANDLE_OCCUPIED (hidden); g_assert (hidden ? occupied : !occupied); - if (!occupied || !MONO_GC_HANDLE_VALID (hidden)) - continue; - revealed = MONO_GC_REVEAL_POINTER (hidden, MONO_GC_HANDLE_TYPE_IS_WEAK (handle_type)); - g_assert (revealed); - if (object_older_than (revealed, max_generation)) + if (!occupied) // || !MONO_GC_HANDLE_VALID (hidden)) continue; - result = callback (revealed, handle_type, user); - if (result) - g_assert (MONO_GC_HANDLE_OCCUPIED (result)); - else + result = callback (hidden, handle_type, max_generation, user); + if (result) { + SGEN_ASSERT (0, MONO_GC_HANDLE_OCCUPIED (result), "Why did the callback return an unoccupied entry?"); + // FIXME: add the dislink_update protocol call here + } else { HEAVY_STAT (InterlockedDecrement64 ((volatile gint64 *)&stat_gc_handles_allocated)); + } entries [offset] = result; } } @@ -1202,27 +1199,36 @@ mono_gchandle_free_domain (MonoDomain *unloading) * Returns whether to remove the link from its hash. */ static gpointer -null_link_if_necessary (GCObject *obj, GCHandleType handle_type, gpointer user) +null_link_if_necessary (gpointer hidden, GCHandleType handle_type, int max_generation, gpointer user) { const gboolean is_weak = GC_HANDLE_TYPE_IS_WEAK (handle_type); ScanCopyContext *ctx = (ScanCopyContext *)user; - GCObject *copy = obj; - g_assert (obj); + GCObject *obj; + GCObject *copy; + + if (!MONO_GC_HANDLE_VALID (hidden)) + return hidden; + + obj = MONO_GC_REVEAL_POINTER (hidden, MONO_GC_HANDLE_TYPE_IS_WEAK (handle_type)); + SGEN_ASSERT (0, obj, "Why is the hidden pointer NULL?"); + + if (object_older_than (obj, max_generation)) + return hidden; + if (major_collector.is_object_live (obj)) - return MONO_GC_HANDLE_OBJECT_POINTER (obj, is_weak); - /* - gboolean obj_in_nursery = ptr_in_nursery (obj); - if (sgen_get_current_collection_generation () == GENERATION_NURSERY && !obj_in_nursery) - return GC_HANDLE_OBJECT_POINTER (obj); - */ + return hidden; + /* Clear link if object is ready for finalization. This check may be redundant wrt is_object_live(). */ - if (sgen_gc_is_object_ready_for_finalization (obj)) { - /* binary_protocol_dislink_update (hidden_entry, entry, 0); */ + if (sgen_gc_is_object_ready_for_finalization (obj)) return MONO_GC_HANDLE_DOMAIN_POINTER (mono_object_domain (obj), is_weak); - } + ctx->ops->copy_or_mark_object (©, ctx->queue); g_assert (copy); /* binary_protocol_dislink_update (hidden_entry, copy, handle_type == HANDLE_WEAK_TRACK); */ + + copy = obj; + ctx->ops->copy_or_mark_object (©, ctx->queue); + SGEN_ASSERT (0, copy, "Why couldn't we copy the object?"); /* Update link if object was moved. */ return MONO_GC_HANDLE_OBJECT_POINTER (copy, is_weak); } @@ -1240,15 +1246,25 @@ typedef struct { } WeakLinkAlivePredicateClosure; static gpointer -null_link_if (GCObject *obj, GCHandleType handle_type, gpointer user) +null_link_if (gpointer hidden, GCHandleType handle_type, int max_generation, gpointer user) { /* Strictly speaking, function pointers are not guaranteed to have the same size as data pointers. */ WeakLinkAlivePredicateClosure *closure = (WeakLinkAlivePredicateClosure *)user; - if (closure->predicate (obj, closure->data)) { - /* binary_protocol_dislink_update (hidden_entry, NULL, 0); */ + GCObject *obj; + + if (!MONO_GC_HANDLE_VALID (hidden)) + return hidden; + + obj = MONO_GC_REVEAL_POINTER (hidden, MONO_GC_HANDLE_TYPE_IS_WEAK (handle_type)); + SGEN_ASSERT (0, obj, "Why is the hidden pointer NULL?"); + + if (object_older_than (obj, max_generation)) + return hidden; + + if (closure->predicate (obj, closure->data)) return NULL; - } - return MONO_GC_HANDLE_OBJECT_POINTER (obj, GC_HANDLE_TYPE_IS_WEAK (handle_type)); + + return hidden; } /* LOCKING: requires that the GC lock is held */ diff --git a/mono/sgen/sgen-gc.h b/mono/sgen/sgen-gc.h index b1102e91746..544d9d2cf6a 100644 --- a/mono/sgen/sgen-gc.h +++ b/mono/sgen/sgen-gc.h @@ -1068,7 +1068,6 @@ gboolean nursery_canaries_enabled (void); #define MONO_GC_HANDLE_OBJECT_POINTER(p,h) (MONO_GC_HIDE_POINTER ((p), MONO_GC_HANDLE_OCCUPIED_MASK | MONO_GC_HANDLE_VALID_MASK, (h))) void sgen_gchandle_set_target (guint32 gchandle, GCObject *obj); -void sgen_gchandle_iterate (GCHandleType handle_type, int max_generation, gpointer callback(GCObject*, GCHandleType, gpointer), gpointer user); void sgen_mark_normal_gc_handles (void *addr, SgenUserMarkFunc mark_func, void *gc_data); #endif /* HAVE_SGEN_GC */ -- 2.25.1