Merge pull request #5714 from alexischr/update_bockbuild
[mono.git] / mono / sgen / sgen-debug.c
index 28e77a77e87d53c9a3145a586f0545f3b049c639..904460bdfdd94e80a2e74651bdef627e484f20d7 100644 (file)
@@ -1,5 +1,6 @@
-/*
- * sgen-debug.c: Collector debugging
+/**
+ * \file
+ * Collector debugging
  *
  * Author:
  *     Paolo Molaro (lupus@ximian.com)
@@ -149,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,7 +183,7 @@ check_consistency_callback (GCObject *obj, 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
 
@@ -196,6 +198,8 @@ 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);
 }
@@ -213,7 +217,7 @@ is_major_or_los_object_marked (GCObject *obj)
 #undef HANDLE_PTR
 #define HANDLE_PTR(ptr,obj)    do {    \
        if (*(ptr) && !sgen_ptr_in_nursery ((char*)*(ptr)) && !is_major_or_los_object_marked ((GCObject*)*(ptr))) { \
-               if (!sgen_get_remset ()->find_address_with_cards (start, cards, (char*)(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))); \
@@ -240,8 +244,6 @@ check_mod_union_callback (GCObject *obj, size_t size, void *dummy)
        else
                cards = sgen_get_major_collector ()->get_cardtable_mod_union_for_reference (start);
 
-       SGEN_ASSERT (0, cards, "we must have mod union for marked major objects");
-
 #include "sgen-scan-object.h"
 }
 
@@ -250,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);
 
@@ -323,7 +325,7 @@ static void
 setup_valid_nursery_objects (void)
 {
        if (!valid_nursery_objects)
-               valid_nursery_objects = (GCObject **)sgen_alloc_os_memory (DEFAULT_NURSERY_SIZE, (SgenAllocFlags)(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, FALSE);
 }
@@ -426,15 +428,15 @@ 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 (*(ptr)) && (!allow_missing_pinned || !SGEN_OBJECT_IS_PINNED (*(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
@@ -442,7 +444,7 @@ verify_object_pointers_callback (GCObject *obj, size_t size, void *data)
 {
        char *start = (char*)obj;
        gboolean allow_missing_pinned = (gboolean) (size_t) data;
-       SgenDescriptor desc = sgen_obj_get_descriptor (obj);
+       SgenDescriptor desc = sgen_obj_get_descriptor_safe (obj);
 
 #include "sgen-scan-object.h"
 }
@@ -493,28 +495,24 @@ static void
 find_pinning_ref_from_thread (char *obj, size_t size)
 {
 #ifndef SGEN_WITHOUT_MONO
-       int j;
        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));
+                               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
@@ -807,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);
@@ -911,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);
@@ -943,12 +959,6 @@ is_xdomain_ref_allowed (GCObject **ptr, GCObject *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
@@ -986,7 +996,8 @@ check_reference_for_xdomain (GCObject **ptr, GCObject *obj, MonoDomain *domain)
        for (klass = obj->vtable->klass; klass; klass = klass->parent) {
                int i;
 
-               for (i = 0; i < klass->field.count; ++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;
@@ -996,9 +1007,11 @@ check_reference_for_xdomain (GCObject **ptr, GCObject *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",
                        obj, obj->vtable->klass->name_space, obj->vtable->klass->name,
@@ -1052,10 +1065,10 @@ 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;
@@ -1070,7 +1083,6 @@ 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;