Permalink
Browse files

[sgen] Incomplete bridge weak reference fix.

This is an incomplete fix for #6715.  After bridge processing we
iterate through all weak references again, this time nulling those
that point to bridged objects that were diagnosed as dead by the
bridge.

As of now it's inefficient because it uses linear search for each weak
reference lookup, as well as incomplete because the code runs while
the world is running, so the weak links might be accessed before they
are consistent.
  • Loading branch information...
1 parent a6fc85b commit 572bd8b01721c4cf423ce1d66f96a195c54f983a @schani schani committed Sep 18, 2012
@@ -572,8 +572,28 @@ sgen_bridge_processing_stw_step (void)
step_2 = SGEN_TV_ELAPSED (btv, atv);
}
+typedef struct {
+ int num_sccs;
+ MonoGCBridgeSCC **sccs;
+} SCCData;
+
+static mono_bool
+is_bridge_object_alive (MonoObject *obj, void *data)
+{
+ SCCData *d = data;
+ int i;
+ for (i = 0; i < d->num_sccs; ++i) {
+ int j;
+ for (j = 0; j < d->sccs [i]->num_objs; ++j) {
+ if (obj == d->sccs [i]->objs [j])
+ return d->sccs [i]->is_alive;
+ }
+ }
+ return TRUE;
+}
+
void
-sgen_bridge_processing_finish (void)
+sgen_bridge_processing_finish (int generation)
{
int i, j;
int num_sccs, num_xrefs;
@@ -585,6 +605,7 @@ sgen_bridge_processing_finish (void)
HashEntry **all_entries;
MonoGCBridgeSCC **api_sccs;
MonoGCBridgeXRef *api_xrefs;
+ SCCData predicate_data;
SGEN_TV_DECLARE (atv);
SGEN_TV_DECLARE (btv);
@@ -667,6 +688,7 @@ sgen_bridge_processing_finish (void)
continue;
api_sccs [j] = sgen_alloc_internal_dynamic (sizeof (MonoGCBridgeSCC) + sizeof (MonoObject*) * scc->num_bridge_entries, INTERNAL_MEM_BRIDGE_DATA, TRUE);
+ api_sccs [j]->is_alive = FALSE;
api_sccs [j]->num_objs = scc->num_bridge_entries;
scc->num_bridge_entries = 0;
scc->api_index = j++;
@@ -734,17 +756,25 @@ sgen_bridge_processing_finish (void)
bridge_callbacks.cross_references (num_sccs, api_sccs, num_xrefs, api_xrefs);
-/*Release for finalization those objects we no longer care. */
+ /* Release for finalization those objects we no longer care. */
SGEN_TV_GETTIME (btv);
step_7 = SGEN_TV_ELAPSED (atv, btv);
for (i = 0; i < num_sccs; ++i) {
- if (!api_sccs [i]->objs [0])
+ if (api_sccs [i]->is_alive)
continue;
for (j = 0; j < api_sccs [i]->num_objs; ++j)
sgen_mark_bridge_object (api_sccs [i]->objs [j]);
}
+ /* Null weak links to dead objects. */
+ predicate_data.num_sccs = num_sccs;
+ predicate_data.sccs = api_sccs;
+
+ sgen_null_links_with_predicate (GENERATION_NURSERY, is_bridge_object_alive, &predicate_data);
+ if (generation == GENERATION_OLD)
+ sgen_null_links_with_predicate (GENERATION_OLD, is_bridge_object_alive, &predicate_data);
+
/* free callback data */
for (i = 0; i < num_sccs; ++i) {
@@ -29,10 +29,11 @@
MONO_BEGIN_DECLS
enum {
- SGEN_BRIDGE_VERSION = 2
+ SGEN_BRIDGE_VERSION = 3
};
typedef struct {
+ mono_bool is_alive; /* to be set by the cross reference callback */
int num_objs;
MonoObject *objs [MONO_ZERO_LEN_ARRAY];
} MonoGCBridgeSCC;
@@ -474,6 +474,32 @@ null_links_for_domain (MonoDomain *domain, int generation)
} SGEN_HASH_TABLE_FOREACH_END;
}
+/* LOCKING: requires that the GC lock is held */
+void
+sgen_null_links_with_predicate (int generation, WeakLinkAlivePredicateFunc predicate, void *data)
+{
+ void **link;
+ gpointer dummy;
+ SgenHashTable *hash = get_dislink_hash_table (generation);
+ fprintf (stderr, "**** nulling links with predicate\n");
+ SGEN_HASH_TABLE_FOREACH (hash, link, dummy) {
+ char *object = DISLINK_OBJECT (link);
+ mono_bool is_alive = predicate ((MonoObject*)object, data);
+
+ if (is_alive)
+ fprintf (stderr, "ALIVE %p %s\n", object, safe_name (object));
+ else
+ fprintf (stderr, "DEAD %p %s\n", object, safe_name (object));
+
+ if (!is_alive) {
+ *link = NULL;
+ DEBUG (5, fprintf (gc_debug_file, "Dislink nullified by predicate at %p to GCed object %p\n", link, object));
+ SGEN_HASH_TABLE_FOREACH_REMOVE (TRUE);
+ continue;
+ }
+ } SGEN_HASH_TABLE_FOREACH_END;
+}
+
static void
remove_finalizers_for_domain (MonoDomain *domain, int generation)
{
View
@@ -1824,9 +1824,9 @@ stw_bridge_process (void)
}
static void
-bridge_process (void)
+bridge_process (int generation)
{
- sgen_bridge_processing_finish ();
+ sgen_bridge_processing_finish (generation);
}
SgenObjectOperations *
@@ -3624,7 +3624,7 @@ restart_world (int generation, GGTimingInfo *timing)
DEBUG (2, fprintf (gc_debug_file, "restarted %d thread(s) (pause time: %d usec, max: %d)\n", count, (int)usec, (int)max_pause_usec));
mono_profiler_gc_event (MONO_GC_EVENT_POST_START_WORLD, generation);
- bridge_process ();
+ bridge_process (generation);
TV_GETTIME (end_bridge);
bridge_usec = TV_ELAPSED (end_sw, end_bridge);
View
@@ -778,7 +778,7 @@ gboolean sgen_object_is_live (void *obj) MONO_INTERNAL;
gboolean sgen_need_bridge_processing (void) MONO_INTERNAL;
void sgen_bridge_reset_data (void) MONO_INTERNAL;
void sgen_bridge_processing_stw_step (void) MONO_INTERNAL;
-void sgen_bridge_processing_finish (void) MONO_INTERNAL;
+void sgen_bridge_processing_finish (int generation) MONO_INTERNAL;
void sgen_register_test_bridge_callbacks (const char *bridge_class_name) MONO_INTERNAL;
gboolean sgen_is_bridge_object (MonoObject *obj) MONO_INTERNAL;
gboolean sgen_is_bridge_class (MonoClass *class) MONO_INTERNAL;
@@ -788,6 +788,9 @@ void sgen_bridge_register_finalized_object (MonoObject *object) MONO_INTERNAL;
void sgen_scan_togglerefs (CopyOrMarkObjectFunc copy_func, char *start, char *end, SgenGrayQueue *queue) MONO_INTERNAL;
void sgen_process_togglerefs (void) MONO_INTERNAL;
+typedef mono_bool (*WeakLinkAlivePredicateFunc) (MonoObject*, void*);
+
+void sgen_null_links_with_predicate (int generation, WeakLinkAlivePredicateFunc predicate, void *data) MONO_INTERNAL;
gboolean sgen_gc_is_object_ready_for_finalization (void *object) MONO_INTERNAL;
void sgen_gc_lock (void) MONO_INTERNAL;

0 comments on commit 572bd8b

Please sign in to comment.