[sgen] More information in describe_ptr(), and unify with describe_pointer().
[mono.git] / mono / metadata / sgen-debug.c
index bbc3478a95ef4e40838839410634a2dbd8df3c45..95a9363e95548ebd6dbab87b3d410ca789c8e6c1 100644 (file)
@@ -8,25 +8,20 @@
  * Copyright 2005-2011 Novell, Inc (http://www.novell.com)
  * Copyright 2011 Xamarin Inc (http://www.xamarin.com)
  * Copyright 2011 Xamarin, Inc.
+ * Copyright (C) 2012 Xamarin Inc
  *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- * 
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- * 
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
- * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
- * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ * 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.
  */
 
 #include "config.h"
@@ -64,16 +59,24 @@ const char*descriptor_types [] = {
        "complex_arr"
 };
 
-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;
        } else {
                if (sgen_ptr_is_in_los (ptr, &start)) {
                        if (ptr == start)
@@ -81,8 +84,17 @@ 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;
-               } else if (major_collector.ptr_is_in_non_pinned_space (ptr)) {
-                       printf ("Pointer inside oldspace.\n");
+                       mono_sgen_los_describe_pointer (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);
+                       else if (start)
+                               printf ("Pointer is at offset 0x%x of object %p in oldspace.\n", (int)(ptr - start), start);
+                       else
+                               printf ("Pointer inside oldspace.\n");
+                       if (start)
+                               ptr = start;
+                       major_collector.describe_pointer (ptr);
                } else if (major_collector.obj_is_from_pinned_alloc (ptr)) {
                        printf ("Pointer is inside a pinned chunk.\n");
                } else {
@@ -94,8 +106,11 @@ describe_ptr (char *ptr)
        if (object_is_pinned (ptr))
                printf ("Object is pinned.\n");
 
-       if (object_is_forwarded (ptr))
-               printf ("Object is forwared.\n");
+       if ((forwarded = object_is_forwarded (ptr))) {
+               printf ("Object is forwarded to %p:\n", forwarded);
+               ptr = forwarded;
+               goto restart;
+       }
 
        // FIXME: Handle pointers to the inside of objects
        vtable = (MonoVTable*)LOAD_VTABLE (ptr);
@@ -116,6 +131,15 @@ 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: %td\n", size);
+}
+
+void
+describe_ptr (char *ptr)
+{
+       describe_pointer (ptr, TRUE);
 }
 
 static gboolean missing_remsets;
@@ -130,7 +154,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))) { \
-                       fprintf (gc_debug_file, "Oldspace->newspace reference %p at offset %td in object %p (%s.%s) not found in remsets.\n", *(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;                                                                 \
@@ -146,7 +170,7 @@ static void
 check_consistency_callback (char *start, size_t size, void *dummy)
 {
        GCVTable *vt = (GCVTable*)LOAD_VTABLE (start);
-       DEBUG (8, fprintf (gc_debug_file, "Scanning object %p, vtable: %p (%s)\n", start, vt, vt->klass->name));
+       SGEN_LOG (8, "Scanning object %p, vtable: %p (%s)", start, vt, vt->klass->name);
 
 #define SCAN_OBJECT_ACTION
 #include "sgen-scan-object.h"
@@ -164,14 +188,14 @@ sgen_check_consistency (void)
 
        missing_remsets = FALSE;
 
-       DEBUG (1, fprintf (gc_debug_file, "Begin heap consistency check...\n"));
+       SGEN_LOG (1, "Begin heap consistency check...");
 
        // Check that oldspace->newspace pointers are registered with the collector
        major_collector.iterate_objects (TRUE, TRUE, (IterateObjectCallbackFunc)check_consistency_callback, NULL);
 
        sgen_los_iterate_objects ((IterateObjectCallbackFunc)check_consistency_callback, NULL);
 
-       DEBUG (1, fprintf (gc_debug_file, "Heap consistency check done.\n"));
+       SGEN_LOG (1, "Heap consistency check done.");
 
        if (!binary_protocol_is_enabled ())
                g_assert (!missing_remsets);
@@ -232,6 +256,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)
 {
@@ -250,31 +283,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;
 
-       fprintf (gc_debug_file, "nursery-ptr ");
+       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) {
-               fprintf (gc_debug_file, "(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)
-                       fprintf (gc_debug_file, "(object %s.%s size %d)", 
-                               vtable->klass->name_space, vtable->klass->name, size);
+                       SGEN_LOG (0, "nursery-ptr\n");
                else
-                       fprintf (gc_debug_file, "(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;
        }
 }
 
@@ -292,30 +323,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)) {
-               fprintf (gc_debug_file, "non-heap-ptr");
-       }
-}
-
 static void
 bad_pointer_spew (char *obj, char **slot)
 {
        char *ptr = *slot;
        MonoVTable *vtable = (MonoVTable*)LOAD_VTABLE (obj);
 
-       fprintf (gc_debug_file, "Invalid object pointer %p [", ptr);
-       describe_pointer (ptr);
-       fprintf (gc_debug_file, "] at offset %td in object %p (%s.%s).\n",
+       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, FALSE);
        broken_heap = TRUE;
 }
 
@@ -325,7 +342,7 @@ missing_remset_spew (char *obj, char **slot)
        char *ptr = *slot;
        MonoVTable *vtable = (MonoVTable*)LOAD_VTABLE (obj);
 
-    fprintf (gc_debug_file,  "Oldspace->newspace reference %p at offset %td in object %p (%s.%s) not found in remsets.\n",
+       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);
 
@@ -362,11 +379,7 @@ depend on OP_DUMMY_USE.
 void
 sgen_check_whole_heap (void)
 {
-       /*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);
@@ -413,7 +426,7 @@ find_pinning_ref_from_thread (char *obj, size_t size)
                        continue;
                while (start < (char**)info->stack_end) {
                        if (*start >= obj && *start < endobj) {
-                               DEBUG (0, fprintf (gc_debug_file, "Object %p referenced in thread %p (id %p) at %p, stack: %p-%p\n", 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++;
                }
@@ -426,7 +439,7 @@ find_pinning_ref_from_thread (char *obj, size_t size)
 #endif
 
                        if (w >= (mword)obj && w < (mword)obj + size)
-                               DEBUG (0, fprintf (gc_debug_file, "Object %p referenced in saved reg %d of thread %p (id %p)\n", 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
        }
 }
@@ -446,7 +459,7 @@ find_pinning_reference (char *obj, size_t size)
                if (!root->root_desc) {
                        while (start < (char**)root->end_root) {
                                if (*start >= obj && *start < endobj) {
-                                       DEBUG (0, fprintf (gc_debug_file, "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++;
                        }