]> granicus.if.org Git - gc/commitdiff
Add assertions to check GC_large_free_bytes and GC_root_size values by
authorIvan Maidanski <ivmai@mail.ru>
Tue, 31 Jan 2012 16:10:14 +0000 (20:10 +0400)
committerIvan Maidanski <ivmai@mail.ru>
Tue, 31 Jan 2012 16:10:14 +0000 (20:10 +0400)
GC_finish_collection even if GC_dump_regularly is off

* allchblk.c (GC_compute_large_free_bytes): New inner function
(defined only if GC_ASSERTIONS or not NO_DEBUGGING).
* mark_rts.c (GC_compute_root_size): Likewise.
* allchblk.c (GC_print_hblkfreelist): Call GC_compute_large_free_bytes
instead of computing large_free_bytes itself (only if not USE_MUNMAP
for now); remove "sz" local variable.
* allchblk.c (GC_print_hblkfreelist): Refine logged messages (for
total value).
* mark_rts.c (GC_print_static_roots): Likewise.
* include/private/gc_priv.h (GC_dump_regularly, COND_DUMP): Move
definition down below GC_ASSERT one.
* include/private/gc_priv.h (GC_compute_large_free_bytes,
GC_compute_root_size): New function declaration (only if
GC_ASSERTIONS).
* include/private/gc_priv.h (COND_DUMP_CHECKS): New macro (invoke
GC_ASSERT for GC_large_free_bytes and GC_root_size).
* include/private/gc_priv.h (COND_DUMP): Invoke COND_DUMP_CHECKS
unless GC_dump_regularly.
* mark_rts.c (GC_print_static_roots): Call GC_compute_root_size
instead of computing root size itself; rename "total" local variable
to "size".

allchblk.c
include/private/gc_priv.h
mark_rts.c

index f6ea681ea9f71453dc15adb963f000ceaac913e8..f8cf2c2c8085a831c2b163aa2d2609a77b355257 100644 (file)
@@ -106,13 +106,34 @@ STATIC int GC_hblk_fl_from_blocks(word blocks_needed)
 #   define IS_MAPPED(hhdr) 1
 # endif /* USE_MUNMAP */
 
+#if (!defined(NO_DEBUGGING) && !defined(USE_MUNMAP)) || defined(GC_ASSERTIONS)
+  /* Should return the same value as GC_large_free_bytes.       */
+  GC_INNER word GC_compute_large_free_bytes(void)
+  {
+#   ifdef USE_MUNMAP
+      return GC_large_free_bytes; /* FIXME: unimplemented */
+#   else
+      struct hblk * h;
+      hdr * hhdr;
+      word total_free = 0;
+      unsigned i;
+
+      for (i = 0; i <= N_HBLK_FLS; ++i) {
+        for (h = GC_hblkfreelist[i]; h != 0; h = hhdr->hb_next) {
+          hhdr = HDR(h);
+          total_free += hhdr->hb_sz;
+        }
+      }
+      return total_free;
+#   endif
+  }
+#endif /* !NO_DEBUGGING || GC_ASSERTIONS */
+
 # if !defined(NO_DEBUGGING)
 void GC_print_hblkfreelist(void)
 {
     struct hblk * h;
-    word total_free = 0;
     hdr * hhdr;
-    word sz;
     unsigned i;
 
     for (i = 0; i <= N_HBLK_FLS; ++i) {
@@ -125,23 +146,25 @@ void GC_print_hblkfreelist(void)
 #     endif
       while (h != 0) {
         hhdr = HDR(h);
-        sz = hhdr -> hb_sz;
-        total_free += sz;
         GC_printf("\t%p size %lu %s black listed\n",
-                (void *)h, (unsigned long)sz,
+                (void *)h, (unsigned long) hhdr -> hb_sz,
                 GC_is_black_listed(h, HBLKSIZE) != 0 ? "start" :
                 GC_is_black_listed(h, hhdr -> hb_sz) != 0 ? "partially" :
                                                         "not");
         h = hhdr -> hb_next;
       }
     }
+    GC_printf("GC_large_free_bytes: %lu\n",
+              (unsigned long)GC_large_free_bytes);
+
 #   ifndef USE_MUNMAP
-      if (total_free != GC_large_free_bytes) {
-        GC_printf("GC_large_free_bytes = %lu (INCONSISTENT!!)\n",
-                  (unsigned long) GC_large_free_bytes);
+      {
+        word total;
+        if ((total = GC_compute_large_free_bytes()) != GC_large_free_bytes)
+          GC_err_printf("GC_large_free_bytes INCONSISTENT!! Should be: %lu\n",
+                        (unsigned long)total);
       }
 #   endif
-    GC_printf("Total of %lu bytes on free list\n", (unsigned long)total_free);
 }
 
 /* Return the free list index on which the block described by the header */
index e98e9d2d322ff2b4ea5b51240a2cda220e3a6402..09584afc89e7852f78bbea3b26c5a7714e0a068d 100644 (file)
@@ -1873,14 +1873,6 @@ GC_EXTERN GC_bool GC_have_errors; /* We saw a smashed or leaked object. */
 #endif
 #define VERBOSE 2
 
-#ifndef NO_DEBUGGING
-  GC_EXTERN GC_bool GC_dump_regularly;
-                                /* Generate regular debugging dumps.    */
-# define COND_DUMP if (EXPECT(GC_dump_regularly, FALSE)) GC_dump()
-#else
-# define COND_DUMP /* empty */
-#endif
-
 #ifdef KEEP_BACK_PTRS
   GC_EXTERN long GC_backtraces;
   GC_INNER void GC_generate_random_backtrace_no_gc(void);
@@ -2179,14 +2171,16 @@ GC_INNER ptr_t GC_store_debug_info(ptr_t p, word sz, const char *str,
 #endif /* NEED_PROC_MAPS */
 
 #ifdef GC_ASSERTIONS
-#  define GC_ASSERT(expr) \
+# define GC_ASSERT(expr) \
                 if (!(expr)) { \
                   GC_err_printf("Assertion failure: %s:%d\n", \
                                 __FILE__, __LINE__); \
                   ABORT("assertion failure"); \
                 }
+  GC_INNER word GC_compute_large_free_bytes(void);
+  GC_INNER word GC_compute_root_size(void);
 #else
-#  define GC_ASSERT(expr)
+# define GC_ASSERT(expr)
 #endif
 
 /* Check a compile time assertion at compile time.  The error   */
@@ -2200,6 +2194,19 @@ GC_INNER ptr_t GC_store_debug_info(ptr_t p, word sz, const char *str,
 # define GC_STATIC_ASSERT(expr) (void)sizeof(char[(expr)? 1 : -1])
 #endif
 
+#define COND_DUMP_CHECKS { \
+          GC_ASSERT(GC_compute_large_free_bytes() == GC_large_free_bytes); \
+          GC_ASSERT(GC_compute_root_size() == GC_root_size); }
+
+#ifndef NO_DEBUGGING
+  GC_EXTERN GC_bool GC_dump_regularly;
+                                /* Generate regular debugging dumps.    */
+# define COND_DUMP { if (EXPECT(GC_dump_regularly, FALSE)) GC_dump(); \
+                        else COND_DUMP_CHECKS; }
+#else
+# define COND_DUMP COND_DUMP_CHECKS
+#endif
+
 #if defined(PARALLEL_MARK)
   /* We need additional synchronization facilities from the thread      */
   /* support.  We believe these are less performance critical           */
index 348d61431e7218c5878dd260bbb9cf29a3bccfb3..8bd9ddc2eeef15b4568ad4578c74569cc9505f14 100644 (file)
@@ -39,25 +39,37 @@ int GC_no_dls = 0;      /* Register dynamic library data segments.      */
 static int n_root_sets = 0;
         /* GC_static_roots[0..n_root_sets) contains the valid root sets. */
 
+#if !defined(NO_DEBUGGING) || defined(GC_ASSERTIONS)
+  /* Should return the same value as GC_root_size.      */
+  GC_INNER word GC_compute_root_size(void)
+  {
+    int i;
+    word size = 0;
+
+    for (i = 0; i < n_root_sets; i++) {
+      size += GC_static_roots[i].r_end - GC_static_roots[i].r_start;
+    }
+    return size;
+  }
+#endif /* !NO_DEBUGGING || GC_ASSERTIONS */
+
 #if !defined(NO_DEBUGGING)
   /* For debugging:     */
   void GC_print_static_roots(void)
   {
     int i;
-    size_t total = 0;
+    word size;
 
     for (i = 0; i < n_root_sets; i++) {
         GC_printf("From %p to %p%s\n",
-                  GC_static_roots[i].r_start,
-                  GC_static_roots[i].r_end,
+                  GC_static_roots[i].r_start, GC_static_roots[i].r_end,
                   GC_static_roots[i].r_tmp ? " (temporary)" : "");
-        total += GC_static_roots[i].r_end - GC_static_roots[i].r_start;
-    }
-    GC_printf("Total size: %lu\n", (unsigned long) total);
-    if (GC_root_size != total) {
-        GC_err_printf("GC_root_size incorrect: %lu!!\n",
-                      (unsigned long) GC_root_size);
     }
+    GC_printf("GC_root_size: %lu\n", (unsigned long)GC_root_size);
+
+    if ((size = GC_compute_root_size()) != GC_root_size)
+      GC_err_printf("GC_root_size incorrect!! Should be: %lu\n",
+                    (unsigned long)size);
   }
 #endif /* !NO_DEBUGGING */