Merge pull request #5714 from alexischr/update_bockbuild
[mono.git] / mono / sgen / sgen-debug.c
index 953570678454ec08d02e34d2a33cadf3cb676440..904460bdfdd94e80a2e74651bdef627e484f20d7 100644 (file)
@@ -1,5 +1,6 @@
-/*
- * sgen-debug.c: Collector debugging
+/**
+ * \file
+ * Collector debugging
  *
  * Author:
  *     Paolo Molaro (lupus@ximian.com)
  * Copyright 2011 Xamarin, Inc.
  * Copyright (C) 2012 Xamarin Inc
  *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License 2.0 as published by the Free Software Foundation;
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License 2.0 along with this library; if not, write to the Free
- * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 
 #include "config.h"
@@ -35,9 +25,6 @@
 #include "mono/sgen/sgen-memory-governor.h"
 #include "mono/sgen/sgen-pinning.h"
 #include "mono/sgen/sgen-client.h"
-#ifndef SGEN_WITHOUT_MONO
-#include "mono/metadata/sgen-bridge-internal.h"
-#endif
 
 #define LOAD_VTABLE    SGEN_LOAD_VTABLE
 
@@ -46,7 +33,7 @@
 #define safe_object_get_size   sgen_safe_object_get_size
 
 void describe_ptr (char *ptr);
-void check_object (char *start);
+void check_object (GCObject *obj);
 
 /*
  * ######################################################################
@@ -70,8 +57,8 @@ static char* describe_nursery_ptr (char *ptr, gboolean need_setup);
 static void
 describe_pointer (char *ptr, gboolean need_setup)
 {
-       GCVTable *vtable;
-       mword desc;
+       GCVTable vtable;
+       SgenDescriptor desc;
        int type;
        char *start;
        char *forwarded;
@@ -83,7 +70,7 @@ describe_pointer (char *ptr, gboolean need_setup)
                if (!start)
                        return;
                ptr = start;
-               vtable = (GCVTable*)LOAD_VTABLE (ptr);
+               vtable = LOAD_VTABLE ((GCObject*)ptr);
        } else {
                if (sgen_ptr_is_in_los (ptr, &start)) {
                        if (ptr == start)
@@ -92,7 +79,7 @@ describe_pointer (char *ptr, gboolean need_setup)
                                printf ("Pointer is at offset 0x%x of object %p in LOS space.\n", (int)(ptr - start), start);
                        ptr = start;
                        mono_sgen_los_describe_pointer (ptr);
-                       vtable = (GCVTable*)LOAD_VTABLE (ptr);
+                       vtable = LOAD_VTABLE ((GCObject*)ptr);
                } else if (major_collector.ptr_is_in_non_pinned_space (ptr, &start)) {
                        if (ptr == start)
                                printf ("Pointer is the start of object %p in oldspace.\n", start);
@@ -102,11 +89,11 @@ describe_pointer (char *ptr, gboolean need_setup)
                                printf ("Pointer inside oldspace.\n");
                        if (start)
                                ptr = start;
-                       vtable = (GCVTable*)major_collector.describe_pointer (ptr);
-               } else if (major_collector.obj_is_from_pinned_alloc (ptr)) {
+                       vtable = (GCVTable)major_collector.describe_pointer (ptr);
+               } else if (major_collector.ptr_is_from_pinned_alloc (ptr)) {
                        // FIXME: Handle pointers to the inside of objects
                        printf ("Pointer is inside a pinned chunk.\n");
-                       vtable = (GCVTable*)LOAD_VTABLE (ptr);
+                       vtable = LOAD_VTABLE ((GCObject*)ptr);
                } else {
                        printf ("Pointer unknown.\n");
                        return;
@@ -116,7 +103,7 @@ describe_pointer (char *ptr, gboolean need_setup)
        if (object_is_pinned (ptr))
                printf ("Object is pinned.\n");
 
-       if ((forwarded = object_is_forwarded (ptr))) {
+       if ((forwarded = (char *)object_is_forwarded (ptr))) {
                printf ("Object is forwarded to %p:\n", forwarded);
                ptr = forwarded;
                goto restart;
@@ -125,15 +112,15 @@ describe_pointer (char *ptr, gboolean need_setup)
        printf ("VTable: %p\n", vtable);
        if (vtable == NULL) {
                printf ("VTable is invalid (empty).\n");
-               goto bridge;
+               goto invalid_vtable;
        }
        if (sgen_ptr_in_nursery (vtable)) {
                printf ("VTable is invalid (points inside nursery).\n");
-               goto bridge;
+               goto invalid_vtable;
        }
        printf ("Class: %s.%s\n", sgen_client_vtable_get_namespace (vtable), sgen_client_vtable_get_name (vtable));
 
-       desc = sgen_vtable_get_descriptor ((GCVTable*)vtable);
+       desc = sgen_vtable_get_descriptor (vtable);
        printf ("Descriptor: %lx\n", (long)desc);
 
        type = desc & DESC_TYPE_MASK;
@@ -142,11 +129,9 @@ describe_pointer (char *ptr, gboolean need_setup)
        size = sgen_safe_object_get_size ((GCObject*)ptr);
        printf ("Size: %d\n", (int)size);
 
bridge:
invalid_vtable:
        ;
-#ifndef SGEN_WITHOUT_MONO
-       sgen_bridge_describe_pointer ((GCObject*)ptr);
-#endif
+       sgen_client_describe_invalid_pointer ((GCObject *) ptr);
 }
 
 void
@@ -165,15 +150,16 @@ static gboolean missing_remsets;
  */
 #undef HANDLE_PTR
 #define HANDLE_PTR(ptr,obj)    do {    \
-       if (*(ptr) && sgen_ptr_in_nursery ((char*)*(ptr))) { \
-               if (!sgen_get_remset ()->find_address ((char*)(ptr)) && !sgen_cement_lookup (*(ptr))) { \
-                       GCVTable *__vt = SGEN_LOAD_VTABLE ((obj));      \
-                       SGEN_LOG (0, "Oldspace->newspace reference %p at offset %zd in object %p (%s.%s) not found in remsets.", *(ptr), (char*)(ptr) - (char*)(obj), (obj), sgen_client_vtable_get_namespace (__vt), sgen_client_vtable_get_name (__vt)); \
-                       binary_protocol_missing_remset ((obj), __vt, (int) ((char*)(ptr) - (char*)(obj)), *(ptr), (gpointer)LOAD_VTABLE(*(ptr)), object_is_pinned (*(ptr))); \
-                       if (!object_is_pinned (*(ptr)))                                                         \
-                               missing_remsets = TRUE;                                                                 \
-               }                                                                                                                               \
-       }                                                                                                                                       \
+               if (*(ptr) && sgen_ptr_in_nursery ((char*)*(ptr))) {    \
+                       if (!sgen_get_remset ()->find_address ((char*)(ptr)) && !sgen_cement_lookup (*(ptr))) { \
+                               GCVTable __vt = SGEN_LOAD_VTABLE (obj); \
+                               gboolean is_pinned = object_is_pinned (*(ptr)); \
+                               SGEN_LOG (0, "Oldspace->newspace reference %p at offset %zd in object %p (%s.%s) not found in remsets%s.", *(ptr), (char*)(ptr) - (char*)(obj), (obj), sgen_client_vtable_get_namespace (__vt), sgen_client_vtable_get_name (__vt), is_pinned ? ", but object is pinned" : ""); \
+                               binary_protocol_missing_remset ((obj), __vt, (int) ((char*)(ptr) - (char*)(obj)), *(ptr), (gpointer)LOAD_VTABLE(*(ptr)), is_pinned); \
+                               if (!is_pinned)                         \
+                                       missing_remsets = TRUE;         \
+                       }                                               \
+               }                                                       \
        } while (0)
 
 /*
@@ -181,10 +167,11 @@ static gboolean missing_remsets;
  * be found in the remembered sets.
  */
 static void
-check_consistency_callback (char *start, size_t size, void *dummy)
+check_consistency_callback (GCObject *obj, size_t size, void *dummy)
 {
-       GCVTable *vt = (GCVTable*)LOAD_VTABLE (start);
-       mword desc = sgen_vtable_get_descriptor ((GCVTable*)vt);
+       char *start = (char*)obj;
+       GCVTable vt = LOAD_VTABLE (obj);
+       SgenDescriptor desc = sgen_vtable_get_descriptor (vt);
        SGEN_LOG (8, "Scanning object %p, vtable: %p (%s)", start, vt, sgen_client_vtable_get_name (vt));
 
 #include "sgen-scan-object.h"
@@ -196,7 +183,7 @@ check_consistency_callback (char *start, size_t size, void *dummy)
  * Assumes the world is stopped.
  */
 void
-sgen_check_consistency (void)
+sgen_check_remset_consistency (void)
 {
        // Need to add more checks
 
@@ -211,12 +198,14 @@ sgen_check_consistency (void)
 
        SGEN_LOG (1, "Heap consistency check done.");
 
+       if (missing_remsets)
+               binary_protocol_flush_buffers (TRUE);
        if (!binary_protocol_is_enabled ())
                g_assert (!missing_remsets);
 }
 
 static gboolean
-is_major_or_los_object_marked (char *obj)
+is_major_or_los_object_marked (GCObject *obj)
 {
        if (sgen_safe_object_get_size ((GCObject*)obj) > SGEN_MAX_SMALL_OBJ_SIZE) {
                return sgen_los_object_is_pinned (obj);
@@ -227,9 +216,9 @@ is_major_or_los_object_marked (char *obj)
 
 #undef HANDLE_PTR
 #define HANDLE_PTR(ptr,obj)    do {    \
-       if (*(ptr) && !sgen_ptr_in_nursery ((char*)*(ptr)) && !is_major_or_los_object_marked ((char*)*(ptr))) { \
-               if (!sgen_get_remset ()->find_address_with_cards (start, cards, (char*)(ptr))) { \
-                       GCVTable *__vt = SGEN_LOAD_VTABLE ((obj));      \
+       if (*(ptr) && !sgen_ptr_in_nursery ((char*)*(ptr)) && !is_major_or_los_object_marked ((GCObject*)*(ptr))) { \
+               if (!cards || !sgen_get_remset ()->find_address_with_cards (start, cards, (char*)(ptr))) { \
+                       GCVTable __vt = SGEN_LOAD_VTABLE (obj); \
                        SGEN_LOG (0, "major->major reference %p at offset %zd in object %p (%s.%s) not found in remsets.", *(ptr), (char*)(ptr) - (char*)(obj), (obj), sgen_client_vtable_get_namespace (__vt), sgen_client_vtable_get_name (__vt)); \
                        binary_protocol_missing_remset ((obj), __vt, (int) ((char*)(ptr) - (char*)(obj)), *(ptr), (gpointer)LOAD_VTABLE(*(ptr)), object_is_pinned (*(ptr))); \
                        missing_remsets = TRUE;                         \
@@ -238,23 +227,22 @@ is_major_or_los_object_marked (char *obj)
        } while (0)
 
 static void
-check_mod_union_callback (char *start, size_t size, void *dummy)
+check_mod_union_callback (GCObject *obj, size_t size, void *dummy)
 {
+       char *start = (char*)obj;
        gboolean in_los = (gboolean) (size_t) dummy;
-       GCVTable *vt = (GCVTable*)LOAD_VTABLE (start);
-       mword desc = sgen_vtable_get_descriptor ((GCVTable*)vt);
+       GCVTable vt = LOAD_VTABLE (obj);
+       SgenDescriptor desc = sgen_vtable_get_descriptor (vt);
        guint8 *cards;
-       SGEN_LOG (8, "Scanning object %p, vtable: %p (%s)", start, vt, sgen_client_vtable_get_name (vt));
+       SGEN_LOG (8, "Scanning object %p, vtable: %p (%s)", obj, vt, sgen_client_vtable_get_name (vt));
 
-       if (!is_major_or_los_object_marked (start))
+       if (!is_major_or_los_object_marked (obj))
                return;
 
        if (in_los)
-               cards = sgen_los_header_for_object (start)->cardtable_mod_union;
+               cards = sgen_los_header_for_object (obj)->cardtable_mod_union;
        else
-               cards = sgen_get_major_collector ()->get_cardtable_mod_union_for_object (start);
-
-       SGEN_ASSERT (0, cards, "we must have mod union for marked major objects");
+               cards = sgen_get_major_collector ()->get_cardtable_mod_union_for_reference (start);
 
 #include "sgen-scan-object.h"
 }
@@ -264,7 +252,7 @@ sgen_check_mod_union_consistency (void)
 {
        missing_remsets = FALSE;
 
-       major_collector.iterate_objects (ITERATE_OBJECTS_ALL, (IterateObjectCallbackFunc)check_mod_union_callback, (void*)FALSE);
+       major_collector.iterate_objects (ITERATE_OBJECTS_SWEEP_ALL, (IterateObjectCallbackFunc)check_mod_union_callback, (void*)FALSE);
 
        sgen_los_iterate_objects ((IterateObjectCallbackFunc)check_mod_union_callback, (void*)TRUE);
 
@@ -279,9 +267,10 @@ sgen_check_mod_union_consistency (void)
        } while (0)
 
 static void
-check_major_refs_callback (char *start, size_t size, void *dummy)
+check_major_refs_callback (GCObject *obj, size_t size, void *dummy)
 {
-       mword desc = sgen_obj_get_descriptor (start);
+       char *start = (char*)obj;
+       SgenDescriptor desc = sgen_obj_get_descriptor (obj);
 
 #include "sgen-scan-object.h"
 }
@@ -308,25 +297,26 @@ sgen_check_major_refs (void)
  * reference fields are valid.
  */
 void
-check_object (char *start)
+check_object (GCObject *obj)
 {
-       mword desc;
+       char *start = (char*)obj;
+       SgenDescriptor desc;
 
        if (!start)
                return;
 
-       desc = sgen_obj_get_descriptor (start);
+       desc = sgen_obj_get_descriptor (obj);
 
 #include "sgen-scan-object.h"
 }
 
 
-static char **valid_nursery_objects;
+static GCObject **valid_nursery_objects;
 static int valid_nursery_object_count;
 static gboolean broken_heap;
 
 static void 
-setup_mono_sgen_scan_area_with_callback (char *object, size_t size, void *data)
+setup_mono_sgen_scan_area_with_callback (GCObject *object, size_t size, void *data)
 {
        valid_nursery_objects [valid_nursery_object_count++] = object;
 }
@@ -335,9 +325,9 @@ static void
 setup_valid_nursery_objects (void)
 {
        if (!valid_nursery_objects)
-               valid_nursery_objects = sgen_alloc_os_memory (DEFAULT_NURSERY_SIZE, SGEN_ALLOC_INTERNAL | SGEN_ALLOC_ACTIVATE, "debugging data");
+               valid_nursery_objects = (GCObject **)sgen_alloc_os_memory (sgen_nursery_max_size, (SgenAllocFlags)(SGEN_ALLOC_INTERNAL | SGEN_ALLOC_ACTIVATE), "debugging data", MONO_MEM_ACCOUNT_SGEN_DEBUGGING);
        valid_nursery_object_count = 0;
-       sgen_scan_area_with_callback (nursery_section->data, nursery_section->end_data, setup_mono_sgen_scan_area_with_callback, NULL, FALSE);
+       sgen_scan_area_with_callback (nursery_section->data, nursery_section->end_data, setup_mono_sgen_scan_area_with_callback, NULL, FALSE, FALSE);
 }
 
 static gboolean
@@ -346,10 +336,10 @@ find_object_in_nursery_dump (char *object)
        int first = 0, last = valid_nursery_object_count;
        while (first < last) {
                int middle = first + ((last - first) >> 1);
-               if (object == valid_nursery_objects [middle])
+               if (object == (char*)valid_nursery_objects [middle])
                        return TRUE;
 
-               if (object < valid_nursery_objects [middle])
+               if (object < (char*)valid_nursery_objects [middle])
                        last = middle;
                else
                        first = middle + 1;
@@ -363,8 +353,8 @@ iterate_valid_nursery_objects (IterateObjectCallbackFunc callback, void *data)
 {
        int i;
        for (i = 0; i < valid_nursery_object_count; ++i) {
-               char *obj = valid_nursery_objects [i];
-               callback (obj, safe_object_get_size ((GCObject*)obj), data);
+               GCObject *obj = valid_nursery_objects [i];
+               callback (obj, safe_object_get_size (obj), data);
        }
 }
 
@@ -377,20 +367,20 @@ describe_nursery_ptr (char *ptr, gboolean need_setup)
                setup_valid_nursery_objects ();
 
        for (i = 0; i < valid_nursery_object_count - 1; ++i) {
-               if (valid_nursery_objects [i + 1] > ptr)
+               if ((char*)valid_nursery_objects [i + 1] > ptr)
                        break;
        }
 
-       if (i >= valid_nursery_object_count || valid_nursery_objects [i] + safe_object_get_size ((GCObject *)valid_nursery_objects [i]) < ptr) {
+       if (i >= valid_nursery_object_count || (char*)valid_nursery_objects [i] + safe_object_get_size (valid_nursery_objects [i]) < ptr) {
                SGEN_LOG (0, "nursery-ptr (unalloc'd-memory)");
                return NULL;
        } else {
-               char *obj = valid_nursery_objects [i];
-               if (obj == ptr)
+               GCObject *obj = valid_nursery_objects [i];
+               if ((char*)obj == ptr)
                        SGEN_LOG (0, "nursery-ptr %p", obj);
                else
-                       SGEN_LOG (0, "nursery-ptr %p (interior-ptr offset %zd)", obj, ptr - obj);
-               return obj;
+                       SGEN_LOG (0, "nursery-ptr %p (interior-ptr offset %zd)", obj, ptr - (char*)obj);
+               return (char*)obj;
        }
 }
 
@@ -412,7 +402,7 @@ static void
 bad_pointer_spew (char *obj, char **slot)
 {
        char *ptr = *slot;
-       GCVTable *vtable = (GCVTable*)LOAD_VTABLE (obj);
+       GCVTable vtable = LOAD_VTABLE ((GCObject*)obj);
 
        SGEN_LOG (0, "Invalid object pointer %p at offset %zd in object %p (%s.%s):", ptr,
                        (char*)slot - obj,
@@ -425,7 +415,7 @@ static void
 missing_remset_spew (char *obj, char **slot)
 {
        char *ptr = *slot;
-       GCVTable *vtable = (GCVTable*)LOAD_VTABLE (obj);
+       GCVTable vtable = LOAD_VTABLE ((GCObject*)obj);
 
        SGEN_LOG (0, "Oldspace->newspace reference %p at offset %zd in object %p (%s.%s) not found in remsets.",
                        ptr, (char*)slot - obj, obj, 
@@ -438,22 +428,23 @@ missing_remset_spew (char *obj, char **slot)
 FIXME Flag missing remsets due to pinning as non fatal
 */
 #undef HANDLE_PTR
-#define HANDLE_PTR(ptr,obj)    do {    \
-               if (*(char**)ptr) {     \
+#define HANDLE_PTR(ptr,obj)    do {                                    \
+               if (*(char**)ptr) {                                     \
                        if (!is_valid_object_pointer (*(char**)ptr)) {  \
-                               bad_pointer_spew ((char*)obj, (char**)ptr);     \
-                       } else if (!sgen_ptr_in_nursery (obj) && sgen_ptr_in_nursery ((char*)*ptr)) {   \
-                               if (!sgen_get_remset ()->find_address ((char*)(ptr)) && !sgen_cement_lookup ((char*)*(ptr)) && (!allow_missing_pinned || !SGEN_OBJECT_IS_PINNED ((char*)*(ptr)))) \
-                               missing_remset_spew ((char*)obj, (char**)ptr);  \
-                       }       \
-        } \
+                               bad_pointer_spew ((char*)obj, (char**)ptr); \
+                       } else if (!sgen_ptr_in_nursery (obj) && sgen_ptr_in_nursery ((char*)*ptr)) { \
+                               if (!allow_missing_pinned && !SGEN_OBJECT_IS_PINNED (*(ptr)) && !sgen_get_remset ()->find_address ((char*)(ptr)) && !sgen_cement_lookup (*(ptr))) \
+                                       missing_remset_spew ((char*)obj, (char**)ptr); \
+                       }                                               \
+               }                                                       \
        } while (0)
 
 static void
-verify_object_pointers_callback (char *start, size_t size, void *data)
+verify_object_pointers_callback (GCObject *obj, size_t size, void *data)
 {
+       char *start = (char*)obj;
        gboolean allow_missing_pinned = (gboolean) (size_t) data;
-       mword desc = sgen_obj_get_descriptor (start);
+       SgenDescriptor desc = sgen_obj_get_descriptor_safe (obj);
 
 #include "sgen-scan-object.h"
 }
@@ -469,7 +460,7 @@ sgen_check_whole_heap (gboolean allow_missing_pinned)
        setup_valid_nursery_objects ();
 
        broken_heap = FALSE;
-       sgen_scan_area_with_callback (nursery_section->data, nursery_section->end_data, verify_object_pointers_callback, (void*) (size_t) allow_missing_pinned, FALSE);
+       sgen_scan_area_with_callback (nursery_section->data, nursery_section->end_data, verify_object_pointers_callback, (void*) (size_t) allow_missing_pinned, FALSE, TRUE);
        major_collector.iterate_objects (ITERATE_OBJECTS_SWEEP_ALL, verify_object_pointers_callback, (void*) (size_t) allow_missing_pinned);
        sgen_los_iterate_objects (verify_object_pointers_callback, (void*) (size_t) allow_missing_pinned);
 
@@ -504,31 +495,26 @@ static void
 find_pinning_ref_from_thread (char *obj, size_t size)
 {
 #ifndef SGEN_WITHOUT_MONO
-       int j;
-       SgenThreadInfo *info;
        char *endobj = obj + size;
 
        FOREACH_THREAD (info) {
+               mword *ctxstart, *ctxcurrent, *ctxend;
                char **start = (char**)info->client_info.stack_start;
                if (info->client_info.skip || info->client_info.gc_disabled)
                        continue;
-               while (start < (char**)info->client_info.stack_end) {
+               while (start < (char**)info->client_info.info.stack_end) {
                        if (*start >= obj && *start < endobj)
-                               SGEN_LOG (0, "Object %p referenced in thread %p (id %p) at %p, stack: %p-%p", obj, info, (gpointer)mono_thread_info_get_tid (info), start, info->client_info.stack_start, info->client_info.stack_end);
+                               SGEN_LOG (0, "Object %p referenced in thread %p (id %p) at %p, stack: %p-%p", obj, info, (gpointer)mono_thread_info_get_tid (info), start, info->client_info.stack_start, info->client_info.info.stack_end);
                        start++;
                }
 
-               for (j = 0; j < ARCH_NUM_REGS; ++j) {
-#ifdef USE_MONO_CTX
-                       mword w = ((mword*)&info->client_info.ctx) [j];
-#else
-                       mword w = (mword)&info->client_info.regs [j];
-#endif
+               for (ctxstart = ctxcurrent = (mword*) &info->client_info.ctx, ctxend = (mword*) (&info->client_info.ctx + 1); ctxcurrent < ctxend; ctxcurrent ++) {
+                       mword w = *ctxcurrent;
 
                        if (w >= (mword)obj && w < (mword)obj + size)
-                               SGEN_LOG (0, "Object %p referenced in saved reg %d of thread %p (id %p)", obj, j, info, (gpointer)mono_thread_info_get_tid (info));
-               } END_FOREACH_THREAD
-       }
+                               SGEN_LOG (0, "Object %p referenced in saved reg %d of thread %p (id %p)", obj, (int) (ctxcurrent - ctxstart), info, (gpointer)mono_thread_info_get_tid (info));
+               }
+       } FOREACH_THREAD_END
 #endif
 }
 
@@ -542,7 +528,7 @@ find_pinning_reference (char *obj, size_t size)
        RootRecord *root;
        char *endobj = obj + size;
 
-       SGEN_HASH_TABLE_FOREACH (&roots_hash [ROOT_TYPE_NORMAL], start, root) {
+       SGEN_HASH_TABLE_FOREACH (&roots_hash [ROOT_TYPE_NORMAL], char **, start, RootRecord *, root) {
                /* if desc is non-null it has precise info */
                if (!root->root_desc) {
                        while (start < (char**)root->end_root) {
@@ -566,31 +552,32 @@ find_pinning_reference (char *obj, size_t size)
                        } else {                                        \
                                mword __size = sgen_safe_object_get_size ((GCObject*)__target); \
                                if (__size <= SGEN_MAX_SMALL_OBJ_SIZE)  \
-                                       g_assert (major_collector.is_object_live (__target)); \
+                                       g_assert (major_collector.is_object_live ((GCObject*)__target)); \
                                else                                    \
-                                       g_assert (sgen_los_object_is_pinned (__target)); \
+                                       g_assert (sgen_los_object_is_pinned ((GCObject*)__target)); \
                        }                                               \
                }                                                       \
        } while (0)
 
 static void
-check_marked_callback (char *start, size_t size, void *dummy)
+check_marked_callback (GCObject *obj, size_t size, void *dummy)
 {
+       char *start = (char*)obj;
        gboolean flag = (gboolean) (size_t) dummy;
-       mword desc;
+       SgenDescriptor desc;
 
        if (sgen_ptr_in_nursery (start)) {
                if (flag)
-                       SGEN_ASSERT (0, SGEN_OBJECT_IS_PINNED (start), "All objects remaining in the nursery must be pinned");
+                       SGEN_ASSERT (0, SGEN_OBJECT_IS_PINNED (obj), "All objects remaining in the nursery must be pinned");
        } else if (flag) {
-               if (!sgen_los_object_is_pinned (start))
+               if (!sgen_los_object_is_pinned (obj))
                        return;
        } else {
-               if (!major_collector.is_object_live (start))
+               if (!major_collector.is_object_live (obj))
                        return;
        }
 
-       desc = sgen_obj_get_descriptor_safe (start);
+       desc = sgen_obj_get_descriptor_safe (obj);
 
 #include "sgen-scan-object.h"
 }
@@ -622,7 +609,7 @@ sgen_check_nursery_objects_pinned (gboolean pinned)
 {
        sgen_clear_nursery_fragments ();
        sgen_scan_area_with_callback (nursery_section->data, nursery_section->end_data,
-                       (IterateObjectCallbackFunc)check_nursery_objects_pinned_callback, (void*) (size_t) pinned /* (void*)&ctx */, FALSE);
+                       (IterateObjectCallbackFunc)check_nursery_objects_pinned_callback, (void*) (size_t) pinned /* (void*)&ctx */, FALSE, TRUE);
 }
 
 static void
@@ -670,7 +657,7 @@ sgen_debug_verify_nursery (gboolean do_dump_nursery_content)
                verify_scan_starts (cur, cur + size);
                is_array_fill = sgen_client_object_is_array_fill ((GCObject*)cur);
                if (do_dump_nursery_content) {
-                       GCVTable *vtable = SGEN_LOAD_VTABLE (cur);
+                       GCVTable vtable = SGEN_LOAD_VTABLE ((GCObject*)cur);
                        if (cur > hole_start)
                                SGEN_LOG (0, "HOLE [%p %p %d]", hole_start, cur, (int)(cur - hole_start));
                        SGEN_LOG (0, "OBJ  [%p %p %d %d %s.%s %d]", cur, cur + size, (int)size, (int)ss,
@@ -678,7 +665,7 @@ sgen_debug_verify_nursery (gboolean do_dump_nursery_content)
                                        is_array_fill);
                }
                if (nursery_canaries_enabled () && !is_array_fill) {
-                       CHECK_CANARY_FOR_OBJECT (cur);
+                       CHECK_CANARY_FOR_OBJECT ((GCObject*)cur, TRUE);
                        CANARIFY_SIZE (size);
                }
                cur += size;
@@ -723,39 +710,40 @@ static gboolean scan_object_for_specific_ref_precise = TRUE;
 #undef HANDLE_PTR
 #define HANDLE_PTR(ptr,obj) do {                                       \
                if ((GCObject*)*(ptr) == key) {                         \
-                       GCVTable *vtable = SGEN_LOAD_VTABLE (*(ptr));   \
+                       GCVTable vtable = SGEN_LOAD_VTABLE (*(ptr));    \
                        g_print ("found ref to %p in object %p (%s.%s) at offset %zd\n", \
                                        key, (obj), sgen_client_vtable_get_namespace (vtable), sgen_client_vtable_get_name (vtable), ((char*)(ptr) - (char*)(obj))); \
                }                                                       \
        } while (0)
 
 static void
-scan_object_for_specific_ref (char *start, GCObject *key)
+scan_object_for_specific_ref (GCObject *obj, GCObject *key)
 {
-       char *forwarded;
+       GCObject *forwarded;
 
-       if ((forwarded = SGEN_OBJECT_IS_FORWARDED (start)))
-               start = forwarded;
+       if ((forwarded = SGEN_OBJECT_IS_FORWARDED (obj)))
+               obj = forwarded;
 
        if (scan_object_for_specific_ref_precise) {
-               mword desc = sgen_obj_get_descriptor_safe (start);
+               char *start = (char*)obj;
+               SgenDescriptor desc = sgen_obj_get_descriptor_safe (obj);
                #include "sgen-scan-object.h"
        } else {
-               mword *words = (mword*)start;
-               size_t size = safe_object_get_size ((GCObject*)start);
+               mword *words = (mword*)obj;
+               size_t size = safe_object_get_size (obj);
                int i;
                for (i = 0; i < size / sizeof (mword); ++i) {
                        if (words [i] == (mword)key) {
-                               GCVTable *vtable = SGEN_LOAD_VTABLE (start);
+                               GCVTable vtable = SGEN_LOAD_VTABLE (obj);
                                g_print ("found possible ref to %p in object %p (%s.%s) at offset %zd\n",
-                                               key, start, sgen_client_vtable_get_namespace (vtable), sgen_client_vtable_get_name (vtable), i * sizeof (mword));
+                                               key, obj, sgen_client_vtable_get_namespace (vtable), sgen_client_vtable_get_name (vtable), i * sizeof (mword));
                        }
                }
        }
 }
 
 static void
-scan_object_for_specific_ref_callback (char *obj, size_t size, GCObject *key)
+scan_object_for_specific_ref_callback (GCObject *obj, size_t size, GCObject *key)
 {
        scan_object_for_specific_ref (obj, key);
 }
@@ -772,7 +760,7 @@ static GCObject *check_key = NULL;
 static RootRecord *check_root = NULL;
 
 static void
-check_root_obj_specific_ref_from_marker (void **obj, void *gc_data)
+check_root_obj_specific_ref_from_marker (GCObject **obj, void *gc_data)
 {
        check_root_obj_specific_ref (check_root, check_key, *obj);
 }
@@ -784,8 +772,8 @@ scan_roots_for_specific_ref (GCObject *key, int root_type)
        RootRecord *root;
        check_key = key;
 
-       SGEN_HASH_TABLE_FOREACH (&roots_hash [root_type], start_root, root) {
-               mword desc = root->root_desc;
+       SGEN_HASH_TABLE_FOREACH (&roots_hash [root_type], void **, start_root, RootRecord *, root) {
+               SgenDescriptor desc = root->root_desc;
 
                check_root = root;
 
@@ -794,13 +782,13 @@ scan_roots_for_specific_ref (GCObject *key, int root_type)
                        desc >>= ROOT_DESC_TYPE_SHIFT;
                        while (desc) {
                                if (desc & 1)
-                                       check_root_obj_specific_ref (root, key, *start_root);
+                                       check_root_obj_specific_ref (root, key, (GCObject *)*start_root);
                                desc >>= 1;
                                start_root++;
                        }
                        return;
                case ROOT_DESC_COMPLEX: {
-                       gsize *bitmap_data = sgen_get_complex_descriptor_bitmap (desc);
+                       gsize *bitmap_data = (gsize *)sgen_get_complex_descriptor_bitmap (desc);
                        int bwords = (int) ((*bitmap_data) - 1);
                        void **start_run = start_root;
                        bitmap_data++;
@@ -809,7 +797,7 @@ scan_roots_for_specific_ref (GCObject *key, int root_type)
                                void **objptr = start_run;
                                while (bmap) {
                                        if (bmap & 1)
-                                               check_root_obj_specific_ref (root, key, *objptr);
+                                               check_root_obj_specific_ref (root, key, (GCObject *)*objptr);
                                        bmap >>= 1;
                                        ++objptr;
                                }
@@ -817,6 +805,15 @@ scan_roots_for_specific_ref (GCObject *key, int root_type)
                        }
                        break;
                }
+               case ROOT_DESC_VECTOR: {
+                       void **p;
+
+                       for (p = start_root; p < (void**)root->end_root; p++) {
+                               if (*p)
+                                       check_root_obj_specific_ref (root, key, (GCObject *)*p);
+                       }
+                       break;
+               }
                case ROOT_DESC_USER: {
                        SgenUserRootMarkFunc marker = sgen_get_user_descriptor_func (desc);
                        marker (start_root, check_root_obj_specific_ref_from_marker, NULL);
@@ -842,7 +839,7 @@ mono_gc_scan_for_specific_ref (GCObject *key, gboolean precise)
        scan_object_for_specific_ref_precise = precise;
 
        sgen_scan_area_with_callback (nursery_section->data, nursery_section->end_data,
-                       (IterateObjectCallbackFunc)scan_object_for_specific_ref_callback, key, TRUE);
+                       (IterateObjectCallbackFunc)scan_object_for_specific_ref_callback, key, TRUE, FALSE);
 
        major_collector.iterate_objects (ITERATE_OBJECTS_SWEEP_ALL, (IterateObjectCallbackFunc)scan_object_for_specific_ref_callback, key);
 
@@ -851,15 +848,15 @@ mono_gc_scan_for_specific_ref (GCObject *key, gboolean precise)
        scan_roots_for_specific_ref (key, ROOT_TYPE_NORMAL);
        scan_roots_for_specific_ref (key, ROOT_TYPE_WBARRIER);
 
-       SGEN_HASH_TABLE_FOREACH (&roots_hash [ROOT_TYPE_PINNED], ptr, root) {
+       SGEN_HASH_TABLE_FOREACH (&roots_hash [ROOT_TYPE_PINNED], void **, ptr, RootRecord *, root) {
                while (ptr < (void**)root->end_root) {
-                       check_root_obj_specific_ref (root, *ptr, key);
+                       check_root_obj_specific_ref (root, (GCObject *)*ptr, key);
                        ++ptr;
                }
        } SGEN_HASH_TABLE_FOREACH_END;
 
        if (sgen_is_world_stopped ())
-               find_pinning_ref_from_thread ((char*)key, sizeof (MonoObject));
+               find_pinning_ref_from_thread ((char*)key, sizeof (GCObject));
 }
 
 #ifndef SGEN_WITHOUT_MONO
@@ -874,9 +871,9 @@ check_obj_not_in_domain (MonoObject **o)
 
 
 static void
-check_obj_not_in_domain_callback (void **o, void *gc_data)
+check_obj_not_in_domain_callback (GCObject **o, void *gc_data)
 {
-       g_assert (((MonoObject*)(*o))->vtable->domain != check_domain);
+       g_assert ((*o)->vtable->domain != check_domain);
 }
 
 void
@@ -885,8 +882,8 @@ sgen_scan_for_registered_roots_in_domain (MonoDomain *domain, int root_type)
        void **start_root;
        RootRecord *root;
        check_domain = domain;
-       SGEN_HASH_TABLE_FOREACH (&roots_hash [root_type], start_root, root) {
-               mword desc = root->root_desc;
+       SGEN_HASH_TABLE_FOREACH (&roots_hash [root_type], void **, start_root, RootRecord *, root) {
+               SgenDescriptor desc = root->root_desc;
 
                /* The MonoDomain struct is allowed to hold
                   references to objects in its own domain. */
@@ -898,13 +895,13 @@ sgen_scan_for_registered_roots_in_domain (MonoDomain *domain, int root_type)
                        desc >>= ROOT_DESC_TYPE_SHIFT;
                        while (desc) {
                                if ((desc & 1) && *start_root)
-                                       check_obj_not_in_domain (*start_root);
+                                       check_obj_not_in_domain ((MonoObject **)*start_root);
                                desc >>= 1;
                                start_root++;
                        }
                        break;
                case ROOT_DESC_COMPLEX: {
-                       gsize *bitmap_data = sgen_get_complex_descriptor_bitmap (desc);
+                       gsize *bitmap_data = (gsize *)sgen_get_complex_descriptor_bitmap (desc);
                        int bwords = (int)((*bitmap_data) - 1);
                        void **start_run = start_root;
                        bitmap_data++;
@@ -913,7 +910,7 @@ sgen_scan_for_registered_roots_in_domain (MonoDomain *domain, int root_type)
                                void **objptr = start_run;
                                while (bmap) {
                                        if ((bmap & 1) && *objptr)
-                                               check_obj_not_in_domain (*objptr);
+                                               check_obj_not_in_domain ((MonoObject **)*objptr);
                                        bmap >>= 1;
                                        ++objptr;
                                }
@@ -921,6 +918,15 @@ sgen_scan_for_registered_roots_in_domain (MonoDomain *domain, int root_type)
                        }
                        break;
                }
+               case ROOT_DESC_VECTOR: {
+                       void **p;
+
+                       for (p = start_root; p < (void**)root->end_root; p++) {
+                               if (*p)
+                                       check_obj_not_in_domain ((MonoObject **)*p);
+                       }
+                       break;
+               }
                case ROOT_DESC_USER: {
                        SgenUserRootMarkFunc marker = sgen_get_user_descriptor_func (desc);
                        marker (start_root, check_obj_not_in_domain_callback, NULL);
@@ -937,10 +943,10 @@ sgen_scan_for_registered_roots_in_domain (MonoDomain *domain, int root_type)
 }
 
 static gboolean
-is_xdomain_ref_allowed (gpointer *ptr, char *obj, MonoDomain *domain)
+is_xdomain_ref_allowed (GCObject **ptr, GCObject *obj, MonoDomain *domain)
 {
        MonoObject *o = (MonoObject*)(obj);
-       MonoObject *ref = (MonoObject*)*(ptr);
+       MonoObject *ref = *ptr;
        size_t offset = (char*)(ptr) - (char*)o;
 
        if (o->vtable->klass == mono_defaults.thread_class && offset == G_STRUCT_OFFSET (MonoThread, internal_thread))
@@ -953,12 +959,6 @@ is_xdomain_ref_allowed (gpointer *ptr, char *obj, MonoDomain *domain)
                        offset == G_STRUCT_OFFSET (MonoRealProxy, unwrapped_server))
                return TRUE;
 #endif
-       /* Thread.cached_culture_info */
-       if (!strcmp (ref->vtable->klass->name_space, "System.Globalization") &&
-                       !strcmp (ref->vtable->klass->name, "CultureInfo") &&
-                       !strcmp(o->vtable->klass->name_space, "System") &&
-                       !strcmp(o->vtable->klass->name, "Object[]"))
-               return TRUE;
        /*
         *  at System.IO.MemoryStream.InternalConstructor (byte[],int,int,bool,bool) [0x0004d] in /home/schani/Work/novell/trunk/mcs/class/corlib/System.IO/MemoryStream.cs:121
         * at System.IO.MemoryStream..ctor (byte[]) [0x00017] in /home/schani/Work/novell/trunk/mcs/class/corlib/System.IO/MemoryStream.cs:81
@@ -979,12 +979,11 @@ is_xdomain_ref_allowed (gpointer *ptr, char *obj, MonoDomain *domain)
 }
 
 static void
-check_reference_for_xdomain (gpointer *ptr, char *obj, MonoDomain *domain)
+check_reference_for_xdomain (GCObject **ptr, GCObject *obj, MonoDomain *domain)
 {
-       MonoObject *o = (MonoObject*)(obj);
-       MonoObject *ref = (MonoObject*)*(ptr);
-       size_t offset = (char*)(ptr) - (char*)o;
-       MonoClass *class;
+       MonoObject *ref = *ptr;
+       size_t offset = (char*)(ptr) - (char*)obj;
+       MonoClass *klass;
        MonoClassField *field;
        char *str;
 
@@ -994,12 +993,13 @@ check_reference_for_xdomain (gpointer *ptr, char *obj, MonoDomain *domain)
                return;
 
        field = NULL;
-       for (class = o->vtable->klass; class; class = class->parent) {
+       for (klass = obj->vtable->klass; klass; klass = klass->parent) {
                int i;
 
-               for (i = 0; i < class->field.count; ++i) {
-                       if (class->fields[i].offset == offset) {
-                               field = &class->fields[i];
+               int fcount = mono_class_get_field_count (klass);
+               for (i = 0; i < fcount; ++i) {
+                       if (klass->fields[i].offset == offset) {
+                               field = &klass->fields[i];
                                break;
                        }
                }
@@ -1007,15 +1007,17 @@ check_reference_for_xdomain (gpointer *ptr, char *obj, MonoDomain *domain)
                        break;
        }
 
-       if (ref->vtable->klass == mono_defaults.string_class)
-               str = mono_string_to_utf8 ((MonoString*)ref);
-       else
+       if (ref->vtable->klass == mono_defaults.string_class) {
+               MonoError error;
+               str = mono_string_to_utf8_checked ((MonoString*)ref, &error);
+               mono_error_cleanup (&error);
+       } else
                str = NULL;
        g_print ("xdomain reference in %p (%s.%s) at offset %d (%s) to %p (%s.%s) (%s)  -  pointed to by:\n",
-                       o, o->vtable->klass->name_space, o->vtable->klass->name,
+                       obj, obj->vtable->klass->name_space, obj->vtable->klass->name,
                        offset, field ? field->name : "",
                        ref, ref->vtable->klass->name_space, ref->vtable->klass->name, str ? str : "");
-       mono_gc_scan_for_specific_ref (o, TRUE);
+       mono_gc_scan_for_specific_ref (obj, TRUE);
        if (str)
                g_free (str);
 }
@@ -1024,11 +1026,12 @@ check_reference_for_xdomain (gpointer *ptr, char *obj, MonoDomain *domain)
 #define HANDLE_PTR(ptr,obj)    check_reference_for_xdomain ((ptr), (obj), domain)
 
 static void
-scan_object_for_xdomain_refs (char *start, mword size, void *data)
+scan_object_for_xdomain_refs (GCObject *obj, mword size, void *data)
 {
-       MonoVTable *vt = (MonoVTable*)SGEN_LOAD_VTABLE (start);
+       char *start = (char*)obj;
+       MonoVTable *vt = SGEN_LOAD_VTABLE (obj);
        MonoDomain *domain = vt->domain;
-       mword desc = sgen_vtable_get_descriptor ((GCVTable*)vt);
+       SgenDescriptor desc = sgen_vtable_get_descriptor (vt);
 
        #include "sgen-scan-object.h"
 }
@@ -1039,12 +1042,12 @@ sgen_check_for_xdomain_refs (void)
        LOSObject *bigobj;
 
        sgen_scan_area_with_callback (nursery_section->data, nursery_section->end_data,
-                       (IterateObjectCallbackFunc)scan_object_for_xdomain_refs, NULL, FALSE);
+                       (IterateObjectCallbackFunc)scan_object_for_xdomain_refs, NULL, FALSE, TRUE);
 
        major_collector.iterate_objects (ITERATE_OBJECTS_SWEEP_ALL, (IterateObjectCallbackFunc)scan_object_for_xdomain_refs, NULL);
 
        for (bigobj = los_object_list; bigobj; bigobj = bigobj->next)
-               scan_object_for_xdomain_refs (bigobj->data, sgen_los_object_size (bigobj), NULL);
+               scan_object_for_xdomain_refs ((GCObject*)bigobj->data, sgen_los_object_size (bigobj), NULL);
 }
 
 #endif
@@ -1062,14 +1065,14 @@ void
 sgen_dump_section (GCMemSection *section, const char *type)
 {
        char *start = section->data;
-       char *end = section->data + section->size;
+       char *end = section->end_data;
        char *occ_start = NULL;
 
-       fprintf (heap_dump_file, "<section type=\"%s\" size=\"%lu\">\n", type, (unsigned long)section->size);
+       fprintf (heap_dump_file, "<section type=\"%s\" size=\"%lu\">\n", type, (unsigned long)(section->end_data - section->data));
 
        while (start < end) {
                guint size;
-               //GCVTable *vt;
+               //GCVTable vt;
                //MonoClass *class;
 
                if (!*(void**)start) {
@@ -1080,12 +1083,11 @@ sgen_dump_section (GCMemSection *section, const char *type)
                        start += sizeof (void*); /* should be ALLOC_ALIGN, really */
                        continue;
                }
-               g_assert (start < section->next_data);
 
                if (!occ_start)
                        occ_start = start;
 
-               //vt = (GCVTable*)SGEN_LOAD_VTABLE (start);
+               //vt = SGEN_LOAD_VTABLE (start);
                //class = vt->klass;
 
                size = SGEN_ALIGN_UP (safe_object_get_size ((GCObject*) start));
@@ -1111,7 +1113,7 @@ dump_object (GCObject *obj, gboolean dump_location)
 #ifndef SGEN_WITHOUT_MONO
        static char class_name [1024];
 
-       MonoClass *class = mono_object_class (obj);
+       MonoClass *klass = mono_object_class (obj);
        int i, j;
 
        /*
@@ -1119,16 +1121,16 @@ dump_object (GCObject *obj, gboolean dump_location)
         * in strings, so we just ignore them;
         */
        i = j = 0;
-       while (class->name [i] && j < sizeof (class_name) - 1) {
-               if (!strchr ("<>\"", class->name [i]))
-                       class_name [j++] = class->name [i];
+       while (klass->name [i] && j < sizeof (class_name) - 1) {
+               if (!strchr ("<>\"", klass->name [i]))
+                       class_name [j++] = klass->name [i];
                ++i;
        }
        g_assert (j < sizeof (class_name));
        class_name [j] = 0;
 
        fprintf (heap_dump_file, "<object class=\"%s.%s\" size=\"%zd\"",
-                       class->name_space, class_name,
+                       klass->name_space, class_name,
                        safe_object_get_size (obj));
        if (dump_location) {
                const char *location;
@@ -1179,7 +1181,7 @@ sgen_debug_dump_heap (const char *type, int num, const char *reason)
        fprintf (heap_dump_file, "<pinned-objects>\n");
        pinned_objects = sgen_pin_stats_get_object_list ();
        for (i = 0; i < pinned_objects->next_slot; ++i)
-               dump_object (pinned_objects->data [i], TRUE);
+               dump_object ((GCObject *)pinned_objects->data [i], TRUE);
        fprintf (heap_dump_file, "</pinned-objects>\n");
 
        sgen_dump_section (nursery_section, "nursery");
@@ -1194,27 +1196,27 @@ sgen_debug_dump_heap (const char *type, int num, const char *reason)
        fprintf (heap_dump_file, "</collection>\n");
 }
 
-static char *found_obj;
+static GCObject *found_obj;
 
 static void
-find_object_for_ptr_callback (char *obj, size_t size, void *user_data)
+find_object_for_ptr_callback (GCObject *obj, size_t size, void *user_data)
 {
-       char *ptr = user_data;
+       char *ptr = (char *)user_data;
 
-       if (ptr >= obj && ptr < obj + size) {
+       if (ptr >= (char*)obj && ptr < (char*)obj + size) {
                g_assert (!found_obj);
                found_obj = obj;
        }
 }
 
 /* for use in the debugger */
-char*
+GCObject*
 sgen_find_object_for_ptr (char *ptr)
 {
        if (ptr >= nursery_section->data && ptr < nursery_section->end_data) {
                found_obj = NULL;
                sgen_scan_area_with_callback (nursery_section->data, nursery_section->end_data,
-                               find_object_for_ptr_callback, ptr, TRUE);
+                               find_object_for_ptr_callback, ptr, TRUE, FALSE);
                if (found_obj)
                        return found_obj;
        }
@@ -1233,169 +1235,4 @@ sgen_find_object_for_ptr (char *ptr)
        return found_obj;
 }
 
-#ifndef SGEN_WITHOUT_MONO
-
-static int
-compare_xrefs (const void *a_ptr, const void *b_ptr)
-{
-       const MonoGCBridgeXRef *a = a_ptr;
-       const MonoGCBridgeXRef *b = b_ptr;
-
-       if (a->src_scc_index < b->src_scc_index)
-               return -1;
-       if (a->src_scc_index > b->src_scc_index)
-               return 1;
-
-       if (a->dst_scc_index < b->dst_scc_index)
-               return -1;
-       if (a->dst_scc_index > b->dst_scc_index)
-               return 1;
-
-       return 0;
-}
-
-/*
-static void
-dump_processor_state (SgenBridgeProcessor *p)
-{
-       int i;
-
-       printf ("------\n");
-       printf ("SCCS %d\n", p->num_sccs);
-       for (i = 0; i < p->num_sccs; ++i) {
-               int j;
-               MonoGCBridgeSCC *scc = p->api_sccs [i];
-               printf ("\tSCC %d:", i);
-               for (j = 0; j < scc->num_objs; ++j) {
-                       MonoObject *obj = scc->objs [j];
-                       printf (" %p", obj);
-               }
-               printf ("\n");
-       }
-
-       printf ("XREFS %d\n", p->num_xrefs);
-       for (i = 0; i < p->num_xrefs; ++i)
-               printf ("\t%d -> %d\n", p->api_xrefs [i].src_scc_index, p->api_xrefs [i].dst_scc_index);
-
-       printf ("-------\n");
-}
-*/
-
-gboolean
-sgen_compare_bridge_processor_results (SgenBridgeProcessor *a, SgenBridgeProcessor *b)
-{
-       int i;
-       SgenHashTable obj_to_a_scc = SGEN_HASH_TABLE_INIT (INTERNAL_MEM_BRIDGE_DEBUG, INTERNAL_MEM_BRIDGE_DEBUG, sizeof (int), mono_aligned_addr_hash, NULL);
-       SgenHashTable b_scc_to_a_scc = SGEN_HASH_TABLE_INIT (INTERNAL_MEM_BRIDGE_DEBUG, INTERNAL_MEM_BRIDGE_DEBUG, sizeof (int), g_direct_hash, NULL);
-       MonoGCBridgeXRef *a_xrefs, *b_xrefs;
-       size_t xrefs_alloc_size;
-
-       // dump_processor_state (a);
-       // dump_processor_state (b);
-
-       if (a->num_sccs != b->num_sccs)
-               g_error ("SCCS count expected %d but got %d", a->num_sccs, b->num_sccs);
-       if (a->num_xrefs != b->num_xrefs)
-               g_error ("SCCS count expected %d but got %d", a->num_xrefs, b->num_xrefs);
-
-       /*
-        * First we build a hash of each object in `a` to its respective SCC index within
-        * `a`.  Along the way we also assert that no object is more than one SCC.
-        */
-       for (i = 0; i < a->num_sccs; ++i) {
-               int j;
-               MonoGCBridgeSCC *scc = a->api_sccs [i];
-
-               g_assert (scc->num_objs > 0);
-
-               for (j = 0; j < scc->num_objs; ++j) {
-                       GCObject *obj = scc->objs [j];
-                       gboolean new_entry = sgen_hash_table_replace (&obj_to_a_scc, obj, &i, NULL);
-                       g_assert (new_entry);
-               }
-       }
-
-       /*
-        * Now we check whether each of the objects in `b` are in `a`, and whether the SCCs
-        * of `b` contain the same sets of objects as those of `a`.
-        *
-        * While we're doing this, build a hash table to map from `b` SCC indexes to `a` SCC
-        * indexes.
-        */
-       for (i = 0; i < b->num_sccs; ++i) {
-               MonoGCBridgeSCC *scc = b->api_sccs [i];
-               MonoGCBridgeSCC *a_scc;
-               int *a_scc_index_ptr;
-               int a_scc_index;
-               int j;
-               gboolean new_entry;
-
-               g_assert (scc->num_objs > 0);
-               a_scc_index_ptr = sgen_hash_table_lookup (&obj_to_a_scc, scc->objs [0]);
-               g_assert (a_scc_index_ptr);
-               a_scc_index = *a_scc_index_ptr;
-
-               //g_print ("A SCC %d -> B SCC %d\n", a_scc_index, i);
-
-               a_scc = a->api_sccs [a_scc_index];
-               g_assert (a_scc->num_objs == scc->num_objs);
-
-               for (j = 1; j < scc->num_objs; ++j) {
-                       a_scc_index_ptr = sgen_hash_table_lookup (&obj_to_a_scc, scc->objs [j]);
-                       g_assert (a_scc_index_ptr);
-                       g_assert (*a_scc_index_ptr == a_scc_index);
-               }
-
-               new_entry = sgen_hash_table_replace (&b_scc_to_a_scc, GINT_TO_POINTER (i), &a_scc_index, NULL);
-               g_assert (new_entry);
-       }
-
-       /*
-        * Finally, check that we have the same xrefs.  We do this by making copies of both
-        * xref arrays, and replacing the SCC indexes in the copy for `b` with the
-        * corresponding indexes in `a`.  Then we sort both arrays and assert that they're
-        * the same.
-        *
-        * At the same time, check that no xref is self-referential and that there are no
-        * duplicate ones.
-        */
-
-       xrefs_alloc_size = a->num_xrefs * sizeof (MonoGCBridgeXRef);
-       a_xrefs = sgen_alloc_internal_dynamic (xrefs_alloc_size, INTERNAL_MEM_BRIDGE_DEBUG, TRUE);
-       b_xrefs = sgen_alloc_internal_dynamic (xrefs_alloc_size, INTERNAL_MEM_BRIDGE_DEBUG, TRUE);
-
-       memcpy (a_xrefs, a->api_xrefs, xrefs_alloc_size);
-       for (i = 0; i < b->num_xrefs; ++i) {
-               MonoGCBridgeXRef *xref = &b->api_xrefs [i];
-               int *scc_index_ptr;
-
-               g_assert (xref->src_scc_index != xref->dst_scc_index);
-
-               scc_index_ptr = sgen_hash_table_lookup (&b_scc_to_a_scc, GINT_TO_POINTER (xref->src_scc_index));
-               g_assert (scc_index_ptr);
-               b_xrefs [i].src_scc_index = *scc_index_ptr;
-
-               scc_index_ptr = sgen_hash_table_lookup (&b_scc_to_a_scc, GINT_TO_POINTER (xref->dst_scc_index));
-               g_assert (scc_index_ptr);
-               b_xrefs [i].dst_scc_index = *scc_index_ptr;
-       }
-
-       qsort (a_xrefs, a->num_xrefs, sizeof (MonoGCBridgeXRef), compare_xrefs);
-       qsort (b_xrefs, a->num_xrefs, sizeof (MonoGCBridgeXRef), compare_xrefs);
-
-       for (i = 0; i < a->num_xrefs; ++i) {
-               g_assert (a_xrefs [i].src_scc_index == b_xrefs [i].src_scc_index);
-               g_assert (a_xrefs [i].dst_scc_index == b_xrefs [i].dst_scc_index);
-       }
-
-       sgen_hash_table_clean (&obj_to_a_scc);
-       sgen_hash_table_clean (&b_scc_to_a_scc);
-       sgen_free_internal_dynamic (a_xrefs, xrefs_alloc_size, INTERNAL_MEM_BRIDGE_DEBUG);
-       sgen_free_internal_dynamic (b_xrefs, xrefs_alloc_size, INTERNAL_MEM_BRIDGE_DEBUG);
-
-       return TRUE;
-}
-
-#endif
-
 #endif /*HAVE_SGEN_GC*/