[sgen] We must do bridge processing with all sgen locks taken.
[mono.git] / mono / metadata / sgen-debug.c
index fb4ce00e3b9a08f409e06e2b348e8d05fb0ed9f3..a04e1a7c1f560aa67041e1fd8b73fe16bd1d4b62 100644 (file)
@@ -29,9 +29,9 @@
 
 #include "metadata/sgen-gc.h"
 #include "metadata/sgen-cardtable.h"
-#include "metadata/sgen-ssb.h"
 #include "metadata/sgen-protocol.h"
 #include "metadata/sgen-memory-governor.h"
+#include "metadata/sgen-pinning.h"
 
 #define LOAD_VTABLE    SGEN_LOAD_VTABLE
 
@@ -49,28 +49,35 @@ void check_object (char *start);
  */
 
 const char*descriptor_types [] = {
+       "INVALID",
        "run_length",
        "small_bitmap",
-       "string",
        "complex",
        "vector",
-       "array",
        "large_bitmap",
-       "complex_arr"
+       "complex_arr",
+       "complex_ptrfree"
 };
 
-void
-describe_ptr (char *ptr)
+static char* describe_nursery_ptr (char *ptr, gboolean need_setup);
+
+static void
+describe_pointer (char *ptr, gboolean need_setup)
 {
        MonoVTable *vtable;
        mword desc;
        int type;
        char *start;
        char *forwarded;
+       mword size;
 
  restart:
        if (sgen_ptr_in_nursery (ptr)) {
-               printf ("Pointer inside nursery.\n");
+               start = describe_nursery_ptr (ptr, need_setup);
+               if (!start)
+                       return;
+               ptr = start;
+               vtable = (MonoVTable*)LOAD_VTABLE (ptr);
        } else {
                if (sgen_ptr_is_in_los (ptr, &start)) {
                        if (ptr == start)
@@ -78,6 +85,8 @@ describe_ptr (char *ptr)
                        else
                                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 = (MonoVTable*)LOAD_VTABLE (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);
@@ -87,8 +96,11 @@ describe_ptr (char *ptr)
                                printf ("Pointer inside oldspace.\n");
                        if (start)
                                ptr = start;
+                       vtable = major_collector.describe_pointer (ptr);
                } else if (major_collector.obj_is_from_pinned_alloc (ptr)) {
+                       // FIXME: Handle pointers to the inside of objects
                        printf ("Pointer is inside a pinned chunk.\n");
+                       vtable = (MonoVTable*)LOAD_VTABLE (ptr);
                } else {
                        printf ("Pointer unknown.\n");
                        return;
@@ -104,17 +116,14 @@ describe_ptr (char *ptr)
                goto restart;
        }
 
-       // FIXME: Handle pointers to the inside of objects
-       vtable = (MonoVTable*)LOAD_VTABLE (ptr);
-
        printf ("VTable: %p\n", vtable);
        if (vtable == NULL) {
                printf ("VTable is invalid (empty).\n");
-               return;
+               goto bridge;
        }
        if (sgen_ptr_in_nursery (vtable)) {
                printf ("VTable is invalid (points inside nursery).\n");
-               return;
+               goto bridge;
        }
        printf ("Class: %s\n", vtable->klass->name);
 
@@ -123,6 +132,18 @@ describe_ptr (char *ptr)
 
        type = desc & 0x7;
        printf ("Descriptor type: %d (%s)\n", type, descriptor_types [type]);
+
+       size = sgen_safe_object_get_size ((MonoObject*)ptr);
+       printf ("Size: %d\n", (int)size);
+
+ bridge:
+       sgen_bridge_describe_pointer ((MonoObject*)ptr);
+}
+
+void
+describe_ptr (char *ptr)
+{
+       describe_pointer (ptr, TRUE);
 }
 
 static gboolean missing_remsets;
@@ -137,7 +158,7 @@ static gboolean missing_remsets;
 #define HANDLE_PTR(ptr,obj)    do {    \
        if (*(ptr) && sgen_ptr_in_nursery ((char*)*(ptr))) { \
                if (!sgen_get_remset ()->find_address ((char*)(ptr))) { \
-                       SGEN_LOG (1, "Oldspace->newspace reference %p at offset %td in object %p (%s.%s) not found in remsets.", *(ptr), (char*)(ptr) - (char*)(obj), (obj), ((MonoObject*)(obj))->vtable->klass->name_space, ((MonoObject*)(obj))->vtable->klass->name); \
+                       SGEN_LOG (0, "Oldspace->newspace reference %p at offset %td in object %p (%s.%s) not found in remsets.", *(ptr), (char*)(ptr) - (char*)(obj), (obj), ((MonoObject*)(obj))->vtable->klass->name_space, ((MonoObject*)(obj))->vtable->klass->name); \
                        binary_protocol_missing_remset ((obj), (gpointer)LOAD_VTABLE ((obj)), (char*)(ptr) - (char*)(obj), *(ptr), (gpointer)LOAD_VTABLE(*(ptr)), object_is_pinned (*(ptr))); \
                        if (!object_is_pinned (*(ptr)))                                                         \
                                missing_remsets = TRUE;                                                                 \
@@ -155,7 +176,6 @@ check_consistency_callback (char *start, size_t size, void *dummy)
        GCVTable *vt = (GCVTable*)LOAD_VTABLE (start);
        SGEN_LOG (8, "Scanning object %p, vtable: %p (%s)", start, vt, vt->klass->name);
 
-#define SCAN_OBJECT_ACTION
 #include "sgen-scan-object.h"
 }
 
@@ -184,6 +204,59 @@ sgen_check_consistency (void)
                g_assert (!missing_remsets);
 }
 
+static gboolean
+is_major_or_los_object_marked (char *obj)
+{
+       if (sgen_safe_object_get_size ((MonoObject*)obj) > SGEN_MAX_SMALL_OBJ_SIZE) {
+               return sgen_los_object_is_pinned (obj);
+       } else {
+               return sgen_get_major_collector ()->is_object_live (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))) { \
+                       SGEN_LOG (0, "major->major reference %p at offset %td in object %p (%s.%s) not found in remsets.", *(ptr), (char*)(ptr) - (char*)(obj), (obj), ((MonoObject*)(obj))->vtable->klass->name_space, ((MonoObject*)(obj))->vtable->klass->name); \
+                       binary_protocol_missing_remset ((obj), (gpointer)LOAD_VTABLE ((obj)), (char*)(ptr) - (char*)(obj), *(ptr), (gpointer)LOAD_VTABLE(*(ptr)), object_is_pinned (*(ptr))); \
+               }                                                                                                                               \
+       }                                                                                                                                       \
+       } while (0)
+
+static void
+check_mod_union_callback (char *start, size_t size, void *dummy)
+{
+       gboolean in_los = (gboolean) (size_t) dummy;
+       GCVTable *vt = (GCVTable*)LOAD_VTABLE (start);
+       guint8 *cards;
+       SGEN_LOG (8, "Scanning object %p, vtable: %p (%s)", start, vt, vt->klass->name);
+
+       if (!is_major_or_los_object_marked (start))
+               return;
+
+       if (in_los)
+               cards = sgen_los_header_for_object (start)->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");
+
+#include "sgen-scan-object.h"
+}
+
+void
+sgen_check_mod_union_consistency (void)
+{
+       missing_remsets = FALSE;
+
+       major_collector.iterate_objects (TRUE, TRUE, (IterateObjectCallbackFunc)check_mod_union_callback, (void*)FALSE);
+
+       sgen_los_iterate_objects ((IterateObjectCallbackFunc)check_mod_union_callback, (void*)TRUE);
+
+       if (!binary_protocol_is_enabled ())
+               g_assert (!missing_remsets);
+}
 
 #undef HANDLE_PTR
 #define HANDLE_PTR(ptr,obj)    do {                                    \
@@ -194,7 +267,6 @@ sgen_check_consistency (void)
 static void
 check_major_refs_callback (char *start, size_t size, void *dummy)
 {
-#define SCAN_OBJECT_ACTION
 #include "sgen-scan-object.h"
 }
 
@@ -239,6 +311,15 @@ setup_mono_sgen_scan_area_with_callback (char *object, size_t size, void *data)
        valid_nursery_objects [valid_nursery_object_count++] = object;
 }
 
+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_object_count = 0;
+       sgen_scan_area_with_callback (nursery_section->data, nursery_section->end_data, setup_mono_sgen_scan_area_with_callback, NULL, FALSE);
+}
+
 static gboolean
 find_object_in_nursery_dump (char *object)
 {
@@ -257,30 +338,29 @@ find_object_in_nursery_dump (char *object)
        return FALSE;
 }
 
-static void
-describe_nursery_ptr (char *ptr)
+static char*
+describe_nursery_ptr (char *ptr, gboolean need_setup)
 {
        int i;
 
+       if (need_setup)
+               setup_valid_nursery_objects ();
+
        for (i = 0; i < valid_nursery_object_count; ++i) {
                if (valid_nursery_objects [i] >= ptr)
                        break;
        }
 
        if (i >= valid_nursery_object_count || valid_nursery_objects [i] + safe_object_get_size ((MonoObject *)valid_nursery_objects [i]) < ptr) {
-               SGEN_LOG (1, "nursery-ptr (unalloc'd-memory)");
+               SGEN_LOG (0, "nursery-ptr (unalloc'd-memory)\n");
+               return NULL;
        } else {
                char *obj = valid_nursery_objects [i];
-               MonoVTable *vtable = (MonoVTable*)LOAD_VTABLE (obj);
-               int size = safe_object_get_size ((MonoObject *)obj);
-
                if (obj == ptr)
-                       SGEN_LOG (1, "nursery-ptr (object %s.%s size %d)", 
-                               vtable->klass->name_space, vtable->klass->name, size);
+                       SGEN_LOG (0, "nursery-ptr\n");
                else
-                       SGEN_LOG (1, "nursery-ptr (interior-ptr offset %td of %p (%s.%s) size %d)",
-                               ptr - obj, obj,
-                               vtable->klass->name_space, vtable->klass->name, size);
+                       SGEN_LOG (0, "nursery-ptr (interior-ptr offset %td)\n", ptr - obj);
+               return obj;
        }
 }
 
@@ -298,29 +378,16 @@ is_valid_object_pointer (char *object)
        return FALSE;
 }
 
-
-static void
-describe_pointer (char *ptr)
-{
-       if (sgen_ptr_in_nursery (ptr)) {
-               describe_nursery_ptr (ptr);
-       } else if (major_collector.describe_pointer (ptr)) {
-               //Nothing really
-       } else if (!mono_sgen_los_describe_pointer (ptr)) {
-               SGEN_LOG (1, "\tnon-heap-ptr");
-       }
-}
-
 static void
 bad_pointer_spew (char *obj, char **slot)
 {
        char *ptr = *slot;
        MonoVTable *vtable = (MonoVTable*)LOAD_VTABLE (obj);
 
-       SGEN_LOG (1, "Invalid object pointer %p at offset %td in object %p (%s.%s):", ptr,
+       SGEN_LOG (0, "Invalid object pointer %p at offset %td in object %p (%s.%s):", ptr,
                (char*)slot - obj,
                obj, vtable->klass->name_space, vtable->klass->name);
-       describe_pointer (ptr);
+       describe_pointer (ptr, FALSE);
        broken_heap = TRUE;
 }
 
@@ -330,7 +397,7 @@ missing_remset_spew (char *obj, char **slot)
        char *ptr = *slot;
        MonoVTable *vtable = (MonoVTable*)LOAD_VTABLE (obj);
 
-    SGEN_LOG (1, "Oldspace->newspace reference %p at offset %td in object %p (%s.%s) not found in remsets.",
+       SGEN_LOG (0, "Oldspace->newspace reference %p at offset %td in object %p (%s.%s) not found in remsets.",
                ptr, (char*)slot - obj, obj, 
                vtable->klass->name_space, vtable->klass->name);
 
@@ -346,16 +413,17 @@ FIXME Flag missing remsets due to pinning as non fatal
                        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))) \
+                               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);  \
                        }       \
         } \
        } while (0)
 
 static void
-verify_object_pointers_callback (char *start, size_t size, void *dummy)
+verify_object_pointers_callback (char *start, size_t size, void *data)
 {
-#define SCAN_OBJECT_ACTION
+       gboolean allow_missing_pinned = (gboolean) (size_t) data;
+
 #include "sgen-scan-object.h"
 }
 
@@ -365,18 +433,14 @@ FIXME:
 depend on OP_DUMMY_USE.
 */
 void
-sgen_check_whole_heap (void)
+sgen_check_whole_heap (gboolean allow_missing_pinned)
 {
-       /*setup valid_nursery_objects*/
-       if (!valid_nursery_objects)
-               valid_nursery_objects = sgen_alloc_os_memory (DEFAULT_NURSERY_SIZE, SGEN_ALLOC_INTERNAL | SGEN_ALLOC_ACTIVATE, "debugging data");
-       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);
+       setup_valid_nursery_objects ();
 
        broken_heap = FALSE;
-       sgen_scan_area_with_callback (nursery_section->data, nursery_section->end_data, verify_object_pointers_callback, NULL, FALSE);
-       major_collector.iterate_objects (TRUE, TRUE, verify_object_pointers_callback, NULL);
-       sgen_los_iterate_objects (verify_object_pointers_callback, NULL);       
+       sgen_scan_area_with_callback (nursery_section->data, nursery_section->end_data, verify_object_pointers_callback, (void*) (size_t) allow_missing_pinned, FALSE);
+       major_collector.iterate_objects (TRUE, TRUE, verify_object_pointers_callback, (void*) (size_t) allow_missing_pinned);
+       sgen_los_iterate_objects (verify_object_pointers_callback, (void*) (size_t) allow_missing_pinned);
 
        g_assert (!broken_heap);
 }
@@ -418,7 +482,7 @@ find_pinning_ref_from_thread (char *obj, size_t size)
                        continue;
                while (start < (char**)info->stack_end) {
                        if (*start >= obj && *start < endobj) {
-                               SGEN_LOG (1, "Object %p referenced in thread %p (id %p) at %p, stack: %p-%p", obj, info, (gpointer)mono_thread_info_get_tid (info), start, info->stack_start, 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->stack_start, info->stack_end);
                        }
                        start++;
                }
@@ -431,7 +495,7 @@ find_pinning_ref_from_thread (char *obj, size_t size)
 #endif
 
                        if (w >= (mword)obj && w < (mword)obj + size)
-                               SGEN_LOG (1, "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, j, info, (gpointer)mono_thread_info_get_tid (info));
                } END_FOREACH_THREAD
        }
 }
@@ -451,7 +515,7 @@ find_pinning_reference (char *obj, size_t size)
                if (!root->root_desc) {
                        while (start < (char**)root->end_root) {
                                if (*start >= obj && *start < endobj) {
-                                       SGEN_LOG (1, "Object %p referenced in pinned roots %p-%p\n", obj, start, root->end_root);
+                                       SGEN_LOG (0, "Object %p referenced in pinned roots %p-%p\n", obj, start, root->end_root);
                                }
                                start++;
                        }
@@ -461,4 +525,66 @@ find_pinning_reference (char *obj, size_t size)
        find_pinning_ref_from_thread (obj, size);
 }
 
+#undef HANDLE_PTR
+#define HANDLE_PTR(ptr,obj)    do {                                    \
+               char* __target = *(char**)ptr;                          \
+               if (__target) {                                         \
+                       g_assert (is_valid_object_pointer (__target));  \
+                       if (sgen_ptr_in_nursery (__target)) {           \
+                               g_assert (SGEN_OBJECT_IS_PINNED (__target)); \
+                       } else if (sgen_los_is_valid_object (__target)) { \
+                               g_assert (sgen_los_object_is_pinned (__target)); \
+                       } else if (major_collector.is_valid_object (__target)) { \
+                               g_assert (major_collector.is_object_live (__target)); \
+                       } else {                                        \
+                               g_assert_not_reached ();                \
+                       }                                               \
+               }                                                       \
+       } while (0)
+
+static void
+check_marked_callback (char *start, size_t size, void *dummy)
+{
+       gboolean is_los = (gboolean) (size_t) dummy;
+
+       if (is_los) {
+               if (!sgen_los_object_is_pinned (start))
+                       return;
+       } else {
+               if (!major_collector.is_object_live (start))
+                       return;
+       }
+
+#include "sgen-scan-object.h"
+}
+
+void
+sgen_check_major_heap_marked (void)
+{
+       setup_valid_nursery_objects ();
+
+       major_collector.iterate_objects (TRUE, TRUE, check_marked_callback, (void*)FALSE);
+       sgen_los_iterate_objects (check_marked_callback, (void*)TRUE);
+}
+
+static void
+check_nursery_objects_pinned_callback (char *obj, size_t size, void *data /* ScanCopyContext *ctx */)
+{
+       gboolean pinned = (gboolean) (size_t) data;
+
+       g_assert (!SGEN_OBJECT_IS_FORWARDED (obj));
+       if (pinned)
+               g_assert (SGEN_OBJECT_IS_PINNED (obj));
+       else
+               g_assert (!SGEN_OBJECT_IS_PINNED (obj));
+}
+
+void
+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);
+}
+
 #endif /*HAVE_SGEN_GC*/