OSDN Git Service

2011-08-11 Richard Guenther <rguenther@suse.de>
[pf3gnuchains/gcc-fork.git] / boehm-gc / dbg_mlc.c
index f640930..061a6a5 100644 (file)
@@ -2,7 +2,8 @@
  * Copyright 1988, 1989 Hans-J. Boehm, Alan J. Demers
  * Copyright (c) 1991-1995 by Xerox Corporation.  All rights reserved.
  * Copyright (c) 1997 by Silicon Graphics.  All rights reserved.
- * Copyright (c) 1999-2000 by Hewlett-Packard Company.  All rights reserved.
+ * Copyright (c) 1999-2004 Hewlett-Packard Development Company, L.P.
+ * Copyright (C) 2007 Free Software Foundation, Inc
  *
  * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
  * OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.
@@ -195,13 +196,13 @@ ptr_t p;
                 (unsigned long)i);
       switch(source) {
        case GC_REFD_FROM_ROOT:
-         GC_err_printf1("root at 0x%lx\n", (unsigned long)base);
+         GC_err_printf1("root at 0x%lx\n\n", (unsigned long)base);
          goto out;
        case GC_REFD_FROM_REG:
-         GC_err_printf0("root in register\n");
+         GC_err_printf0("root in register\n\n");
          goto out;
        case GC_FINALIZER_REFD:
-         GC_err_printf0("list of finalizable objects\n");
+         GC_err_printf0("list of finalizable objects\n\n");
          goto out;
        case GC_REFD_FROM_HEAP:
          GC_err_printf1("offset %ld in object:\n", (unsigned long)offset);
@@ -217,15 +218,20 @@ ptr_t p;
 
   /* Force a garbage collection and generate a backtrace from a        */
   /* random heap address.                                      */
-  void GC_generate_random_backtrace(void)
+  void GC_generate_random_backtrace_no_gc(void)
   {
     void * current;
-    GC_gcollect();
     current = GC_generate_random_valid_address();
-    GC_printf1("Chose address 0x%lx in object\n", (unsigned long)current);
+    GC_printf1("\n****Chose address 0x%lx in object\n", (unsigned long)current);
     GC_print_backtrace(current);
   }
     
+  void GC_generate_random_backtrace(void)
+  {
+    GC_gcollect();
+    GC_generate_random_backtrace_no_gc();
+  }
+    
 #endif /* KEEP_BACK_PTRS */
 
 # define CROSSES_HBLK(p, sz) \
@@ -325,6 +331,58 @@ register oh * ohdr;
 }
 #endif /* !SHORT_DBG_HDRS */
 
+static GC_describe_type_fn GC_describe_type_fns[MAXOBJKINDS] = {0};
+
+void GC_register_describe_type_fn(kind, fn)
+int kind;
+GC_describe_type_fn fn;
+{
+  GC_describe_type_fns[kind] = fn;
+}
+
+/* Print a type description for the object whose client-visible address        */
+/* is p.                                                               */
+void GC_print_type(p)
+ptr_t p;
+{
+    hdr * hhdr = GC_find_header(p);
+    char buffer[GC_TYPE_DESCR_LEN + 1];
+    int kind = hhdr -> hb_obj_kind;
+
+    if (0 != GC_describe_type_fns[kind] && GC_is_marked(GC_base(p))) {
+       /* This should preclude free list objects except with   */
+       /* thread-local allocation.                             */
+       buffer[GC_TYPE_DESCR_LEN] = 0;
+       (GC_describe_type_fns[kind])(p, buffer);
+       GC_ASSERT(buffer[GC_TYPE_DESCR_LEN] == 0);
+       GC_err_puts(buffer);
+    } else {
+       switch(kind) {
+         case PTRFREE:
+           GC_err_puts("PTRFREE");
+           break;
+         case NORMAL:
+           GC_err_puts("NORMAL");
+           break;
+         case UNCOLLECTABLE:
+           GC_err_puts("UNCOLLECTABLE");
+           break;
+#        ifdef ATOMIC_UNCOLLECTABLE
+           case AUNCOLLECTABLE:
+             GC_err_puts("ATOMIC UNCOLLECTABLE");
+             break;
+#        endif
+         case STUBBORN:
+           GC_err_puts("STUBBORN");
+           break;
+         default:
+           GC_err_printf2("kind %ld, descr 0x%lx", kind, hhdr -> hb_descr);
+       }
+    }
+}
+
+    
+
 void GC_print_obj(p)
 ptr_t p;
 {
@@ -334,11 +392,13 @@ ptr_t p;
     GC_err_printf1("0x%lx (", ((unsigned long)ohdr + sizeof(oh)));
     GC_err_puts(ohdr -> oh_string);
 #   ifdef SHORT_DBG_HDRS
-      GC_err_printf1(":%ld)\n", (unsigned long)(ohdr -> oh_int));
+      GC_err_printf1(":%ld", (unsigned long)(ohdr -> oh_int));
 #   else
-      GC_err_printf2(":%ld, sz=%ld)\n", (unsigned long)(ohdr -> oh_int),
+      GC_err_printf2(":%ld, sz=%ld", (unsigned long)(ohdr -> oh_int),
                                        (unsigned long)(ohdr -> oh_sz));
 #   endif
+    GC_print_type((ptr_t)(ohdr + 1));
+    GC_err_puts(")\n");
     PRINT_CALL_CHAIN(ohdr);
 }
 
@@ -403,6 +463,8 @@ void GC_start_debugging()
     GC_register_displacement((word)sizeof(oh));
 }
 
+size_t GC_debug_header_size = sizeof(oh);
+
 # if defined(__STDC__) || defined(__cplusplus)
     void GC_debug_register_displacement(GC_word offset)
 # else
@@ -757,7 +819,15 @@ GC_PTR p;
                    uncollectable = TRUE;
            }
 #      endif
-       if (uncollectable) GC_free(base);
+       if (uncollectable) {
+           GC_free(base);
+       } else {
+           size_t i;
+           size_t obj_sz = hhdr -> hb_sz - BYTES_TO_WORDS(sizeof(oh));
+
+           for (i = 0; i < obj_sz; ++i) ((word *)p)[i] = 0xdeadbeef;
+           GC_ASSERT((word *)p + i == (word *)base + hhdr -> hb_sz);
+       }
     } /* !GC_find_leak */
 }
 
@@ -1013,7 +1083,8 @@ GC_PTR *ocd;
     GC_finalization_proc my_old_fn;
     GC_PTR my_old_cd;
     ptr_t base = GC_base(obj);
-    if (0 == base || (ptr_t)obj - base != sizeof(oh)) {
+    if (0 == base) return;
+    if ((ptr_t)obj - base != sizeof(oh)) {
         GC_err_printf1(
            "GC_debug_register_finalizer called with non-base-pointer 0x%lx\n",
            obj);
@@ -1045,10 +1116,11 @@ GC_PTR *ocd;
     GC_finalization_proc my_old_fn;
     GC_PTR my_old_cd;
     ptr_t base = GC_base(obj);
-    if (0 == base || (ptr_t)obj - base != sizeof(oh)) {
+    if (0 == base) return;
+    if ((ptr_t)obj - base != sizeof(oh)) {
         GC_err_printf1(
-         "GC_debug_register_finalizer_no_order called with non-base-pointer 0x%lx\n",
-         obj);
+           "GC_debug_register_finalizer_no_order called with non-base-pointer 0x%lx\n",
+           obj);
     }
     if (0 == fn) {
       GC_register_finalizer_no_order(base, 0, 0, &my_old_fn, &my_old_cd);
@@ -1058,7 +1130,41 @@ GC_PTR *ocd;
                                     &my_old_cd);
     }
     store_old(obj, my_old_fn, (struct closure *)my_old_cd, ofn, ocd);
- }
+}
+
+# ifdef __STDC__
+    void GC_debug_register_finalizer_unreachable
+                                   (GC_PTR obj, GC_finalization_proc fn,
+                                    GC_PTR cd, GC_finalization_proc *ofn,
+                                    GC_PTR *ocd)
+# else
+    void GC_debug_register_finalizer_unreachable
+                                   (obj, fn, cd, ofn, ocd)
+    GC_PTR obj;
+    GC_finalization_proc fn;
+    GC_PTR cd;
+    GC_finalization_proc *ofn;
+    GC_PTR *ocd;
+# endif
+{
+    GC_finalization_proc my_old_fn;
+    GC_PTR my_old_cd;
+    ptr_t base = GC_base(obj);
+    if (0 == base) return;
+    if ((ptr_t)obj - base != sizeof(oh)) {
+        GC_err_printf1(
+           "GC_debug_register_finalizer_unreachable called with non-base-pointer 0x%lx\n",
+           obj);
+    }
+    if (0 == fn) {
+      GC_register_finalizer_unreachable(base, 0, 0, &my_old_fn, &my_old_cd);
+    } else {
+      GC_register_finalizer_unreachable(base, GC_debug_invoke_finalizer,
+                                    GC_make_closure(fn,cd), &my_old_fn,
+                                    &my_old_cd);
+    }
+    store_old(obj, my_old_fn, (struct closure *)my_old_cd, ofn, ocd);
+}
 
 # ifdef __STDC__
     void GC_debug_register_finalizer_ignore_self
@@ -1078,7 +1184,8 @@ GC_PTR *ocd;
     GC_finalization_proc my_old_fn;
     GC_PTR my_old_cd;
     ptr_t base = GC_base(obj);
-    if (0 == base || (ptr_t)obj - base != sizeof(oh)) {
+    if (0 == base) return;
+    if ((ptr_t)obj - base != sizeof(oh)) {
         GC_err_printf1(
            "GC_debug_register_finalizer_ignore_self called with non-base-pointer 0x%lx\n",
            obj);