+
+#ifdef OLD_XREFS
+ /* If xrefs is a copy then we haven't set a single flag. */
+ if (dyn_array_int_is_copy (¤t_scc->old_xrefs))
+ return;
+ for (i = 0; i < dyn_array_int_size (¤t_scc->old_xrefs); ++i) {
+ int j = dyn_array_int_get (¤t_scc->old_xrefs, i);
+ SCC *bridge_scc = dyn_array_scc_get_ptr (&sccs, j);
+ g_assert (bridge_scc->flag);
+ bridge_scc->flag = FALSE;
+ }
+#endif
+}
+
+#ifdef NEW_XREFS
+static void
+gather_xrefs (SCC *scc)
+{
+ int i;
+ for (i = 0; i < dyn_array_int_size (&scc->new_xrefs); ++i) {
+ int index = dyn_array_int_get (&scc->new_xrefs, i);
+ SCC *src = dyn_array_scc_get_ptr (&sccs, index);
+ if (src->flag)
+ continue;
+ src->flag = TRUE;
+ if (src->num_bridge_entries)
+ dyn_array_int_add (&merge_array, index);
+ else
+ gather_xrefs (src);
+ }
+}
+
+static void
+reset_flags (SCC *scc)
+{
+ int i;
+ for (i = 0; i < dyn_array_int_size (&scc->new_xrefs); ++i) {
+ int index = dyn_array_int_get (&scc->new_xrefs, i);
+ SCC *src = dyn_array_scc_get_ptr (&sccs, index);
+ if (!src->flag)
+ continue;
+ src->flag = FALSE;
+ if (!src->num_bridge_entries)
+ reset_flags (src);
+ }
+}
+#endif
+
+static char *dump_prefix = NULL;
+
+static void
+dump_graph (void)
+{
+ static int counter = 0;
+
+ MonoObject *obj;
+ HashEntry *entry;
+ size_t prefix_len = strlen (dump_prefix);
+ char *filename = alloca(prefix_len + 64);
+ FILE *file;
+ int edge_id = 0;
+
+ sprintf (filename, "%s.%d.gexf", dump_prefix, counter++);
+ file = fopen (filename, "w");
+
+ if (file == NULL) {
+ fprintf (stderr, "Warning: Could not open bridge dump file `%s` for writing: %s\n", filename, strerror (errno));
+ return;
+ }
+
+ fprintf (file, "<gexf xmlns=\"http://www.gexf.net/1.2draft\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://www.gexf.net/1.2draft http://www.gexf.net/1.2draft/gexf.xsd\" version=\"1.2\">\n");
+
+ fprintf (file, "<graph defaultedgetype=\"directed\">\n"
+ "<attributes class=\"node\">\n"
+ "<attribute id=\"0\" title=\"class\" type=\"string\"/>\n"
+ "<attribute id=\"1\" title=\"bridge\" type=\"boolean\"/>\n"
+ "</attributes>\n");
+
+ fprintf (file, "<nodes>\n");
+ SGEN_HASH_TABLE_FOREACH (&hash_table, obj, entry) {
+ MonoVTable *vt = (MonoVTable*) SGEN_LOAD_VTABLE (obj);
+ fprintf (file, "<node id=\"%p\"><attvalues><attvalue for=\"0\" value=\"%s.%s\"/><attvalue for=\"1\" value=\"%s\"/></attvalues></node>\n",
+ obj, vt->klass->name_space, vt->klass->name, entry->is_bridge ? "true" : "false");
+ } SGEN_HASH_TABLE_FOREACH_END;
+ fprintf (file, "</nodes>\n");
+
+ fprintf (file, "<edges>\n");
+ SGEN_HASH_TABLE_FOREACH (&hash_table, obj, entry) {
+ int i;
+ for (i = 0; i < dyn_array_ptr_size (&entry->srcs); ++i) {
+ HashEntry *src = dyn_array_ptr_get (&entry->srcs, i);
+ fprintf (file, "<edge id=\"%d\" source=\"%p\" target=\"%p\"/>\n", edge_id++, sgen_hash_table_key_for_value_pointer (src), obj);
+ }
+ } SGEN_HASH_TABLE_FOREACH_END;
+ fprintf (file, "</edges>\n");
+
+ fprintf (file, "</graph></gexf>\n");
+
+ fclose (file);
+}
+
+static void
+set_dump_prefix (const char *prefix)
+{
+ dump_prefix = strdup (prefix);