[Gc] mark bits for uncollectable

Bruce Hoult bruce at hoult.org
Wed Oct 25 20:37:10 PDT 2006


Hi,

I'm doing some memory use tuning of a GC'd application and the
treatment of mark bits for uncollectable (both atomic and otherwise)
has become really really annoying becuase it is very difficult to
figure out how many such objects are in use in e.g. the output from
GC_dump().

What's worse is that I really don't understand the reasons for the
current system at all.  Why set all the mark bits in the block, not
just the ones that correspond to the start of an object?  And they
don't even stay set.  You get blocks with close to, but not actually,
256 bits set.

The attached patch (to a modified gc6.7, but I'm sure it will match up
fine) works perfectly in our very GC-intensive application, and has
the benefit of the mark bits behaving exactly the same for
uncollectable objects as for any other ... a mark bit is set if and
only if it corresponds to the first word of an allocated object.  It's
just that it stays set from the time the object is allocated until the
time (if ever) that GC_free() is called on it.

Is there some non-obvious reason that this is a bad idea?  The only
thing I can think of is if there is a memory-stomper bug that nukes
the mark bits.  I'll try to avoid those ;-)

Thanks,
Bruce

p.s. there's a faster implementation of counting mark bits for free too :-)

------------ patch follows -------------
Index: mallocx.c
===================================================================
--- mallocx.c   (revision 7081)
+++ mallocx.c   (working copy)
@@ -583,9 +583,7 @@
             *opp = obj_link(op);
             obj_link(op) = 0;
             GC_words_allocd += lw;
-            /* Mark bit ws already set on free list.  It will be       */
-           /* cleared only temporarily during a collection, as a       */
-           /* result of the normal free list mark bit clearing.        */
+            GC_set_mark_bit(op);
             GC_non_gc_bytes += WORDS_TO_BYTES(lw);
             FASTUNLOCK();
             return((GC_PTR) op);
@@ -687,7 +685,7 @@
             *opp = obj_link(op);
             obj_link(op) = 0;
             GC_words_allocd += lw;
-           /* Mark bit was already set while object was on free list. */
+            GC_set_mark_bit(op);
             GC_non_gc_bytes += WORDS_TO_BYTES(lw);
             FASTUNLOCK();
             return((GC_PTR) op);
Index: malloc.c
===================================================================
--- malloc.c    (revision 7081)
+++ malloc.c    (working copy)
@@ -519,9 +519,10 @@
        /* A signal here can make GC_mem_freed and GC_non_gc_bytes      */
        /* inconsistent.  We claim this is benign.                      */
        if (IS_UNCOLLECTABLE(knd)) GC_non_gc_bytes -= WORDS_TO_BYTES(sz);
-               /* Its unnecessary to clear the mark bit.  If the       */
-               /* object is reallocated, it doesn't matter.  O.w. the  */
-               /* collector will do it, since it's on a free list.     */
+       /* Its unnecessary to clear the mark bit.  But it's tidier to debug
+          and it is needed to allow the obj to be reallocated before the
+          next GC? */
+       GC_clear_mark_bit(p);
        if (ok -> ok_init) {
            BZERO((word *)p + 1, WORDS_TO_BYTES(sz-1));
        }
@@ -565,6 +566,7 @@
     if (sz <= MAXOBJSZ) {
        GC_mem_freed += sz;
        if (IS_UNCOLLECTABLE(knd)) GC_non_gc_bytes -= WORDS_TO_BYTES(sz);
+       GC_clear_mark_bit(p);
        if (ok -> ok_init) {
            BZERO((word *)p + 1, WORDS_TO_BYTES(sz-1));
        }
Index: reclaim.c
===================================================================
--- reclaim.c   (revision 7081)
+++ reclaim.c   (working copy)
@@ -733,7 +733,6 @@
             break;
       }
     }
-    if (IS_UNCOLLECTABLE(hhdr -> hb_obj_kind)) GC_set_hdr_marks(hhdr);
     return result;
 }

@@ -865,9 +864,9 @@
     register word m = n;
     register int result = 0;

-    while (m > 0) {
-       if (m & 1) result++;
-       m >>= 1;
+    while (m != 0) {
+       result++;
+       m &= m - 1;
     }
     return(result);
 }
Index: new_hblk.c
===================================================================
--- new_hblk.c  (revision 7081)
+++ new_hblk.c  (working copy)
@@ -257,9 +257,6 @@
     h = GC_allochblk(sz, kind, 0);
     if (h == 0) return;

-  /* Mark all objects if appropriate. */
-      if (IS_UNCOLLECTABLE(kind)) GC_set_hdr_marks(HDR(h));
-
   /* Build the free list */
       GC_obj_kinds[kind].ok_freelist[sz] =
        GC_build_fl(h, sz, clear, GC_obj_kinds[kind].ok_freelist[sz]);


More information about the Gc mailing list