]> git.llucax.com Git - software/dgc/cdgc.git/blobdiff - rt/gc/cdgc/gc.d
Call memset() only for large enough chunks of data
[software/dgc/cdgc.git] / rt / gc / cdgc / gc.d
index 16fcbca9e01b53554ed986ecf4880927fae067fe..e7fdbd2832b9b4208d8f1c5fb55b79972f8a5aa5 100644 (file)
@@ -31,7 +31,6 @@ module rt.gc.cdgc.gc;
 /************** Debugging ***************************/
 
 //debug = COLLECT_PRINTF;       // turn on printf's
 /************** Debugging ***************************/
 
 //debug = COLLECT_PRINTF;       // turn on printf's
-//debug = LOGGING;              // log allocations / frees
 //debug = MEMSTOMP;             // stomp on memory
 //debug = SENTINEL;             // add underrun/overrrun protection
 //debug = PTRCHECK;             // more pointer checking
 //debug = MEMSTOMP;             // stomp on memory
 //debug = SENTINEL;             // add underrun/overrrun protection
 //debug = PTRCHECK;             // more pointer checking
@@ -48,10 +47,27 @@ version = STACKGROWSDOWN;       // growing the stack means subtracting from the
 import rt.gc.cdgc.bits: GCBits;
 import rt.gc.cdgc.stats: GCStats;
 import alloc = rt.gc.cdgc.alloc;
 import rt.gc.cdgc.bits: GCBits;
 import rt.gc.cdgc.stats: GCStats;
 import alloc = rt.gc.cdgc.alloc;
+import rt.gc.cdgc.dynarray: DynArray;
 
 import cstdlib = tango.stdc.stdlib;
 import cstring = tango.stdc.string;
 
 
 import cstdlib = tango.stdc.stdlib;
 import cstring = tango.stdc.string;
 
+/*
+ * This is a small optimization that proved it's usefulness. For small chunks
+ * or memory memset() seems to be slower (probably because of the call) that
+ * simply doing a simple loop to set the memory.
+ */
+void memset(void* dst, int c, size_t n)
+{
+    // This number (32) has been determined empirically
+    if (n > 32) {
+        cstring.memset(dst, c, n);
+        return;
+    }
+    auto p = cast(ubyte*)(dst);
+    while (n-- > 0)
+        *p++ = c;
+}
 
 version (GNU)
 {
 
 version (GNU)
 {
@@ -112,106 +128,6 @@ private
 alias GC gc_t;
 
 
 alias GC gc_t;
 
 
-/* ======================= Leak Detector =========================== */
-
-
-debug (LOGGING)
-{
-    struct Log
-    {
-        void*  p;
-        size_t size;
-        size_t line;
-        char*  file;
-        void*  parent;
-
-        void print()
-        {
-            printf("    p = %x, size = %d, parent = %x ", p, size, parent);
-            if (file)
-            {
-                printf("%s(%u)", file, line);
-            }
-            printf("\n");
-        }
-    }
-
-
-    struct LogArray
-    {
-        size_t dim;
-        size_t allocdim;
-        Log *data;
-
-        void Dtor()
-        {
-            if (data)
-                cstdlib.free(data);
-            data = null;
-        }
-
-        void reserve(size_t nentries)
-        {
-            assert(dim <= allocdim);
-            if (allocdim - dim < nentries)
-            {
-                allocdim = (dim + nentries) * 2;
-                assert(dim + nentries <= allocdim);
-                if (!data)
-                {
-                    data = cast(Log*) cstdlib.malloc(allocdim * Log.sizeof);
-                    if (!data && allocdim)
-                        onOutOfMemoryError();
-                }
-                else
-                {
-                    Log *newdata = cast(Log*) cstdlib.malloc(
-                            allocdim * Log.sizeof);
-                    if (!newdata && allocdim)
-                        onOutOfMemoryError();
-                    cstring.memcpy(newdata, data, dim * Log.sizeof);
-                    cstdlib.free(data);
-                    data = newdata;
-                }
-            }
-        }
-
-
-        void push(Log log)
-        {
-            reserve(1);
-            data[dim++] = log;
-        }
-
-        void remove(size_t i)
-        {
-            cstring.memmove(data + i, data + i + 1, (dim - i) * Log.sizeof);
-            dim--;
-        }
-
-
-        size_t find(void *p)
-        {
-            for (size_t i = 0; i < dim; i++)
-            {
-                if (data[i].p == p)
-                    return i;
-            }
-            return OPFAIL; // not found
-        }
-
-
-        void copy(LogArray *from)
-        {
-            reserve(from.dim - dim);
-            assert(from.dim <= allocdim);
-            cstring.memcpy(data, from.data, from.dim * Log.sizeof);
-            dim = from.dim;
-        }
-    }
-}
-
-
 /* ============================ GC =============================== */
 
 
 /* ============================ GC =============================== */
 
 
@@ -244,17 +160,6 @@ class GC
     }
 
 
     }
 
 
-    void Dtor()
-    {
-        if (gcx)
-        {
-            gcx.Dtor();
-            cstdlib.free(gcx);
-            gcx = null;
-        }
-    }
-
-
     /**
      *
      */
     /**
      *
      */
@@ -480,8 +385,8 @@ class GC
             // Return next item from free list
             gcx.bucket[bin] = (cast(List*)p).next;
             if( !(bits & BlkAttr.NO_SCAN) )
             // Return next item from free list
             gcx.bucket[bin] = (cast(List*)p).next;
             if( !(bits & BlkAttr.NO_SCAN) )
-                cstring.memset(p + size, 0, binsize[bin] - size);
-            debug (MEMSTOMP) cstring.memset(p, 0xF0, size);
+                memset(p + size, 0, binsize[bin] - size);
+            debug (MEMSTOMP) memset(p, 0xF0, size);
         }
         else
         {
         }
         else
         {
@@ -492,7 +397,6 @@ class GC
         size -= SENTINEL_EXTRA;
         p = sentinel_add(p);
         sentinel_init(p, size);
         size -= SENTINEL_EXTRA;
         p = sentinel_add(p);
         sentinel_init(p, size);
-        gcx.log_malloc(p, size);
 
         if (bits)
         {
 
         if (bits)
         {
@@ -534,7 +438,7 @@ class GC
         assert(size != 0);
 
         void *p = mallocNoSync(size, bits);
         assert(size != 0);
 
         void *p = mallocNoSync(size, bits);
-        cstring.memset(p, 0, size);
+        memset(p, 0, size);
         return p;
     }
 
         return p;
     }
 
@@ -628,7 +532,7 @@ class GC
                         synchronized (gcLock)
                         {
                             debug (MEMSTOMP)
                         synchronized (gcLock)
                         {
                             debug (MEMSTOMP)
-                                cstring.memset(p + size, 0xF2, psize - size);
+                                memset(p + size, 0xF2, psize - size);
                             pool.freePages(pagenum + newsz, psz - newsz);
                         }
                         return p;
                             pool.freePages(pagenum + newsz, psz - newsz);
                         }
                         return p;
@@ -643,9 +547,9 @@ class GC
                                 if (i == pagenum + newsz)
                                 {
                                     debug (MEMSTOMP)
                                 if (i == pagenum + newsz)
                                 {
                                     debug (MEMSTOMP)
-                                        cstring.memset(p + psize, 0xF0,
+                                        memset(p + psize, 0xF0,
                                                 size - psize);
                                                 size - psize);
-                                    cstring.memset(pool.pagetable + pagenum +
+                                    memset(pool.pagetable + pagenum +
                                             psz, B_PAGEPLUS, newsz - psz);
                                     return p;
                                 }
                                             psz, B_PAGEPLUS, newsz - psz);
                                     return p;
                                 }
@@ -757,8 +661,8 @@ class GC
         if (sz < minsz)
             return 0;
         debug (MEMSTOMP)
         if (sz < minsz)
             return 0;
         debug (MEMSTOMP)
-            cstring.memset(p + psize, 0xF0, (psz + sz) * PAGESIZE - psize);
-        cstring.memset(pool.pagetable + pagenum + psz, B_PAGEPLUS, sz);
+            memset(p + psize, 0xF0, (psz + sz) * PAGESIZE - psize);
+        memset(pool.pagetable + pagenum + psz, B_PAGEPLUS, sz);
         gcx.p_cache = null;
         gcx.size_cache = 0;
         return (psz + sz) * PAGESIZE;
         gcx.p_cache = null;
         gcx.size_cache = 0;
         return (psz + sz) * PAGESIZE;
@@ -849,7 +753,7 @@ class GC
             size_t n = pagenum;
             while (++n < pool.npages && pool.pagetable[n] == B_PAGEPLUS)
                 npages++;
             size_t n = pagenum;
             while (++n < pool.npages && pool.pagetable[n] == B_PAGEPLUS)
                 npages++;
-            debug (MEMSTOMP) cstring.memset(p, 0xF2, npages * PAGESIZE);
+            debug (MEMSTOMP) memset(p, 0xF2, npages * PAGESIZE);
             pool.freePages(pagenum, npages);
         }
         else
             pool.freePages(pagenum, npages);
         }
         else
@@ -857,12 +761,11 @@ class GC
             // Add to free list
             List *list = cast(List*)p;
 
             // Add to free list
             List *list = cast(List*)p;
 
-            debug (MEMSTOMP) cstring.memset(p, 0xF2, binsize[bin]);
+            debug (MEMSTOMP) memset(p, 0xF2, binsize[bin]);
 
             list.next = gcx.bucket[bin];
             gcx.bucket[bin] = list;
         }
 
             list.next = gcx.bucket[bin];
             gcx.bucket[bin] = list;
         }
-        gcx.log_free(sentinel_add(p));
     }
 
 
     }
 
 
@@ -1103,11 +1006,13 @@ class GC
 
         if (!thread_needLock())
         {
 
         if (!thread_needLock())
         {
-            gcx.addRoot(p);
+            if (roots.append(p) is null)
+                onOutOfMemoryError();
         }
         else synchronized (gcLock)
         {
         }
         else synchronized (gcLock)
         {
-            gcx.addRoot(p);
+            if (roots.append(p) is null)
+                onOutOfMemoryError();
         }
     }
 
         }
     }
 
@@ -1122,14 +1027,16 @@ class GC
             return;
         }
 
             return;
         }
 
+        bool r;
         if (!thread_needLock())
         {
         if (!thread_needLock())
         {
-            gcx.removeRoot(p);
+            r = roots.remove(p);
         }
         else synchronized (gcLock)
         {
         }
         else synchronized (gcLock)
         {
-            gcx.removeRoot(p);
+            r = roots.remove(p);
         }
         }
+        assert (r);
     }
 
 
     }
 
 
@@ -1145,11 +1052,13 @@ class GC
 
         if (!thread_needLock())
         {
 
         if (!thread_needLock())
         {
-            gcx.addRange(p, p + sz);
+            if (ranges.append(Range(p, p+sz)) is null)
+                onOutOfMemoryError();
         }
         else synchronized (gcLock)
         {
         }
         else synchronized (gcLock)
         {
-            gcx.addRange(p, p + sz);
+            if (ranges.append(Range(p, p+sz)) is null)
+                onOutOfMemoryError();
         }
     }
 
         }
     }
 
@@ -1164,14 +1073,16 @@ class GC
             return;
         }
 
             return;
         }
 
+        bool r;
         if (!thread_needLock())
         {
         if (!thread_needLock())
         {
-            gcx.removeRange(p);
+            r = ranges.remove(Range(p, null));
         }
         else synchronized (gcLock)
         {
         }
         else synchronized (gcLock)
         {
-            gcx.removeRange(p);
+            r = ranges.remove(Range(p, null));
         }
         }
+        assert (r);
     }
 
 
     }
 
 
@@ -1196,7 +1107,6 @@ class GC
             getStats(stats);
         }
 
             getStats(stats);
         }
 
-        gcx.log_collect();
     }
 
 
     }
 
 
@@ -1265,11 +1175,11 @@ class GC
         size_t n;
         size_t bsize = 0;
 
         size_t n;
         size_t bsize = 0;
 
-        cstring.memset(&stats, 0, GCStats.sizeof);
+        memset(&stats, 0, GCStats.sizeof);
 
 
-        for (n = 0; n < gcx.npools; n++)
+        for (n = 0; n < pools.length; n++)
         {
         {
-            Pool *pool = gcx.pooltable[n];
+            Pool* pool = pools[n];
             psize += pool.npages * PAGESIZE;
             for (size_t j = 0; j < pool.npages; j++)
             {
             psize += pool.npages * PAGESIZE;
             for (size_t j = 0; j < pool.npages; j++)
             {
@@ -1422,6 +1332,13 @@ struct Range
 {
     void *pbot;
     void *ptop;
 {
     void *pbot;
     void *ptop;
+    int opCmp(in Range other)
+    {
+        if (pbot < other.pbot)
+            return -1;
+        else
+        return cast(int)(pbot > other.pbot);
+    }
 }
 
 
 }
 
 
@@ -1429,6 +1346,13 @@ const uint binsize[B_MAX] = [ 16,32,64,128,256,512,1024,2048,4096 ];
 const uint notbinsize[B_MAX] = [ ~(16u-1),~(32u-1),~(64u-1),~(128u-1),~(256u-1),
                                 ~(512u-1),~(1024u-1),~(2048u-1),~(4096u-1) ];
 
 const uint notbinsize[B_MAX] = [ ~(16u-1),~(32u-1),~(64u-1),~(128u-1),~(256u-1),
                                 ~(512u-1),~(1024u-1),~(2048u-1),~(4096u-1) ];
 
+DynArray!(void*) roots;
+
+DynArray!(Range) ranges;
+
+DynArray!(Pool) pools;
+
+
 /* ============================ Gcx =============================== */
 
 
 /* ============================ Gcx =============================== */
 
 
@@ -1438,14 +1362,6 @@ struct Gcx
     void *p_cache;
     size_t size_cache;
 
     void *p_cache;
     size_t size_cache;
 
-    size_t nroots;
-    size_t rootdim;
-    void **roots;
-
-    size_t nranges;
-    size_t rangedim;
-    Range *ranges;
-
     uint noStack;       // !=0 means don't scan stack
     uint log;           // turn on logging
     uint anychanges;
     uint noStack;       // !=0 means don't scan stack
     uint log;           // turn on logging
     uint anychanges;
@@ -1456,9 +1372,6 @@ struct Gcx
     byte *minAddr;      // min(baseAddr)
     byte *maxAddr;      // max(topAddr)
 
     byte *minAddr;      // min(baseAddr)
     byte *maxAddr;      // max(topAddr)
 
-    size_t npools;
-    Pool **pooltable;
-
     List *bucket[B_MAX];        // free list for each size
 
 
     List *bucket[B_MAX];        // free list for each size
 
 
@@ -1467,33 +1380,11 @@ struct Gcx
         int dummy;
         (cast(byte*)this)[0 .. Gcx.sizeof] = 0;
         stackBottom = cast(char*)&dummy;
         int dummy;
         (cast(byte*)this)[0 .. Gcx.sizeof] = 0;
         stackBottom = cast(char*)&dummy;
-        log_init();
         //printf("gcx = %p, self = %x\n", this, self);
         inited = 1;
     }
 
 
         //printf("gcx = %p, self = %x\n", this, self);
         inited = 1;
     }
 
 
-    void Dtor()
-    {
-        inited = 0;
-
-        for (size_t i = 0; i < npools; i++)
-        {
-            Pool *pool = pooltable[i];
-            pool.Dtor();
-            cstdlib.free(pool);
-        }
-        if (pooltable)
-            cstdlib.free(pooltable);
-
-        if (roots)
-            cstdlib.free(roots);
-
-        if (ranges)
-            cstdlib.free(ranges);
-    }
-
-
     void Invariant() { }
 
 
     void Invariant() { }
 
 
@@ -1504,41 +1395,32 @@ struct Gcx
         //printf("Gcx.invariant(): this = %p\n", this);
             size_t i;
 
         //printf("Gcx.invariant(): this = %p\n", this);
             size_t i;
 
-            for (i = 0; i < npools; i++)
+            for (i = 0; i < pools.length; i++)
             {
             {
-                Pool *pool = pooltable[i];
+                Pool* pool = pools[i];
                 pool.Invariant();
                 if (i == 0)
                 {
                     assert(minAddr == pool.baseAddr);
                 }
                 pool.Invariant();
                 if (i == 0)
                 {
                     assert(minAddr == pool.baseAddr);
                 }
-                if (i + 1 < npools)
+                if (i + 1 < pools.length)
                 {
                 {
-                    assert(pool.opCmp(pooltable[i + 1]) < 0);
+                    assert(*pool < pools[i + 1]);
                 }
                 }
-                else if (i + 1 == npools)
+                else if (i + 1 == pools.length)
                 {
                     assert(maxAddr == pool.topAddr);
                 }
             }
 
                 {
                     assert(maxAddr == pool.topAddr);
                 }
             }
 
-            if (roots)
-            {
-                assert(rootdim != 0);
-                assert(nroots <= rootdim);
-            }
+            roots.Invariant();
+            ranges.Invariant();
 
 
-            if (ranges)
+            for (i = 0; i < ranges.length; i++)
             {
             {
-                assert(rangedim != 0);
-                assert(nranges <= rangedim);
-
-                for (i = 0; i < nranges; i++)
-                {
-                    assert(ranges[i].pbot);
-                    assert(ranges[i].ptop);
-                    assert(ranges[i].pbot <= ranges[i].ptop);
-                }
+                assert(ranges[i].pbot);
+                assert(ranges[i].ptop);
+                assert(ranges[i].pbot <= ranges[i].ptop);
             }
 
             for (i = 0; i < B_PAGE; i++)
             }
 
             for (i = 0; i < B_PAGE; i++)
@@ -1551,120 +1433,23 @@ struct Gcx
     }
 
 
     }
 
 
-    /**
-     *
-     */
-    void addRoot(void *p)
-    {
-        if (nroots == rootdim)
-        {
-            size_t newdim = rootdim * 2 + 16;
-            void** newroots;
-
-            newroots = cast(void**) cstdlib.malloc(newdim * newroots[0].sizeof);
-            if (!newroots)
-                onOutOfMemoryError();
-            if (roots)
-            {
-                cstring.memcpy(newroots, roots, nroots * newroots[0].sizeof);
-                cstdlib.free(roots);
-            }
-            roots = newroots;
-            rootdim = newdim;
-        }
-        roots[nroots] = p;
-        nroots++;
-    }
-
-
-    /**
-     *
-     */
-    void removeRoot(void *p)
-    {
-        for (size_t i = nroots; i--;)
-        {
-            if (roots[i] == p)
-            {
-                nroots--;
-                cstring.memmove(roots + i, roots + i + 1,
-                        (nroots - i) * roots[0].sizeof);
-                return;
-            }
-        }
-        assert(0);
-    }
-
-
-    /**
-     *
-     */
-    void addRange(void *pbot, void *ptop)
-    {
-        if (nranges == rangedim)
-        {
-            size_t newdim = rangedim * 2 + 16;
-            Range *newranges;
-
-            newranges = cast(Range*) cstdlib.malloc(newdim * Range.sizeof);
-            if (!newranges)
-                onOutOfMemoryError();
-            if (ranges)
-            {
-                cstring.memcpy(newranges, ranges, nranges * Range.sizeof);
-                cstdlib.free(ranges);
-            }
-            ranges = newranges;
-            rangedim = newdim;
-        }
-        ranges[nranges].pbot = pbot;
-        ranges[nranges].ptop = ptop;
-        nranges++;
-    }
-
-
-    /**
-     *
-     */
-    void removeRange(void *pbot)
-    {
-        for (size_t i = nranges; i--;)
-        {
-            if (ranges[i].pbot == pbot)
-            {
-                nranges--;
-                cstring.memmove(ranges + i, ranges + i + 1,
-                        (nranges - i) * ranges[0].sizeof);
-                return;
-            }
-        }
-
-        // This is a fatal error, but ignore it.
-        // The problem is that we can get a Close() call on a thread
-        // other than the one the range was allocated on.
-        //assert(zero);
-    }
-
-
     /**
      * Find Pool that pointer is in.
      * Return null if not in a Pool.
     /**
      * Find Pool that pointer is in.
      * Return null if not in a Pool.
-     * Assume pooltable[] is sorted.
+     * Assume pools is sorted.
      */
     Pool *findPool(void *p)
     {
         if (p >= minAddr && p < maxAddr)
         {
      */
     Pool *findPool(void *p)
     {
         if (p >= minAddr && p < maxAddr)
         {
-            if (npools == 1)
+            if (pools.length == 1)
             {
             {
-                return pooltable[0];
+                return pools[0];
             }
 
             }
 
-            for (size_t i = 0; i < npools; i++)
+            for (size_t i = 0; i < pools.length; i++)
             {
             {
-                Pool *pool;
-
-                pool = pooltable[i];
+                Pool* pool = pools[i];
                 if (p < pool.topAddr)
                 {
                     if (pool.baseAddr <= p)
                 if (p < pool.topAddr)
                 {
                     if (pool.baseAddr <= p)
@@ -1866,7 +1651,7 @@ struct Gcx
 
     /**
      * Allocate a new pool of at least size bytes.
 
     /**
      * Allocate a new pool of at least size bytes.
-     * Sort it into pooltable[].
+     * Sort it into pools.
      * Mark all memory in the pool as B_FREE.
      * Return the actual number of bytes reserved or 0 on error.
      */
      * Mark all memory in the pool as B_FREE.
      * Return the actual number of bytes reserved or 0 on error.
      */
@@ -1890,27 +1675,22 @@ struct Gcx
         size_t pn;
         Pool*  pool;
 
         size_t pn;
         Pool*  pool;
 
-        for (n = 0; n < npools; n++)
+        for (n = 0; n < pools.length; n++)
         {
         {
-            pool = pooltable[n];
+            pool = pools[n];
             for (pn = 0; pn < pool.npages; pn++)
             {
                 if (cast(Bins)pool.pagetable[pn] != B_FREE)
                     break;
             }
             if (pn < pool.npages)
             for (pn = 0; pn < pool.npages; pn++)
             {
                 if (cast(Bins)pool.pagetable[pn] != B_FREE)
                     break;
             }
             if (pn < pool.npages)
-            {
-                n++;
                 continue;
                 continue;
-            }
             pool.Dtor();
             pool.Dtor();
-            cstdlib.free(pool);
-            cstring.memmove(pooltable + n,
-                            pooltable + n + 1,
-                            (--npools - n) * (Pool*).sizeof);
-            minAddr = pooltable[0].baseAddr;
-            maxAddr = pooltable[npools - 1].topAddr;
+            pools.remove_at(n);
+            n--;
         }
         }
+        minAddr = pools[0].baseAddr;
+        maxAddr = pools[pools.length - 1].topAddr;
     }
 
 
     }
 
 
@@ -1935,9 +1715,9 @@ struct Gcx
             // This code could use some refinement when repeatedly
             // allocating very large arrays.
 
             // This code could use some refinement when repeatedly
             // allocating very large arrays.
 
-            for (n = 0; n < npools; n++)
+            for (n = 0; n < pools.length; n++)
             {
             {
-                pool = pooltable[n];
+                pool = pools[n];
                 pn = pool.allocPages(npages);
                 if (pn != OPFAIL)
                     goto L1;
                 pn = pool.allocPages(npages);
                 if (pn != OPFAIL)
                     goto L1;
@@ -1954,7 +1734,7 @@ struct Gcx
                 }
                 // Try collecting
                 freedpages = fullcollectshell();
                 }
                 // Try collecting
                 freedpages = fullcollectshell();
-                if (freedpages >= npools * ((POOLSIZE / PAGESIZE) / 4))
+                if (freedpages >= pools.length * ((POOLSIZE / PAGESIZE) / 4))
                 {
                     state = 1;
                     continue;
                 {
                     state = 1;
                     continue;
@@ -1991,10 +1771,10 @@ struct Gcx
       L1:
         pool.pagetable[pn] = B_PAGE;
         if (npages > 1)
       L1:
         pool.pagetable[pn] = B_PAGE;
         if (npages > 1)
-            cstring.memset(&pool.pagetable[pn + 1], B_PAGEPLUS, npages - 1);
+            memset(&pool.pagetable[pn + 1], B_PAGEPLUS, npages - 1);
         p = pool.baseAddr + pn * PAGESIZE;
         p = pool.baseAddr + pn * PAGESIZE;
-        cstring.memset(cast(char *)p + size, 0, npages * PAGESIZE - size);
-        debug (MEMSTOMP) cstring.memset(p, 0xF1, size);
+        memset(cast(char *)p + size, 0, npages * PAGESIZE - size);
+        debug (MEMSTOMP) memset(p, 0xF1, size);
         return p;
 
       Lnomemory:
         return p;
 
       Lnomemory:
@@ -2004,16 +1784,11 @@ struct Gcx
 
     /**
      * Allocate a new pool with at least npages in it.
 
     /**
      * Allocate a new pool with at least npages in it.
-     * Sort it into pooltable[].
+     * Sort it into pools.
      * Return null if failed.
      */
     Pool *newPool(size_t npages)
     {
      * Return null if failed.
      */
     Pool *newPool(size_t npages)
     {
-        Pool*  pool;
-        Pool** newpooltable;
-        size_t newnpools;
-        size_t i;
-
         // Minimum of POOLSIZE
         if (npages < POOLSIZE/PAGESIZE)
             npages = POOLSIZE/PAGESIZE;
         // Minimum of POOLSIZE
         if (npages < POOLSIZE/PAGESIZE)
             npages = POOLSIZE/PAGESIZE;
@@ -2026,9 +1801,9 @@ struct Gcx
         }
 
         // Allocate successively larger pools up to 8 megs
         }
 
         // Allocate successively larger pools up to 8 megs
-        if (npools)
+        if (pools.length)
         {
         {
-            size_t n = npools;
+            size_t n = pools.length;
             if (n > 8)
                 n = 8;                  // cap pool size at 8 megs
             n *= (POOLSIZE / PAGESIZE);
             if (n > 8)
                 n = 8;                  // cap pool size at 8 megs
             n *= (POOLSIZE / PAGESIZE);
@@ -2036,41 +1811,21 @@ struct Gcx
                 npages = n;
         }
 
                 npages = n;
         }
 
-        pool = cast(Pool *) cstdlib.calloc(1, Pool.sizeof);
-        if (pool)
+        Pool p;
+        p.initialize(npages);
+        if (!p.baseAddr)
         {
         {
-            pool.initialize(npages);
-            if (!pool.baseAddr)
-                goto Lerr;
-
-            newnpools = npools + 1;
-            newpooltable = cast(Pool **) cstdlib.realloc(pooltable,
-                    newnpools * (Pool *).sizeof);
-            if (!newpooltable)
-                goto Lerr;
-
-            // Sort pool into newpooltable[]
-            for (i = 0; i < npools; i++)
-            {
-                if (pool.opCmp(newpooltable[i]) < 0)
-                     break;
-            }
-            cstring.memmove(newpooltable + i + 1, newpooltable + i,
-                    (npools - i) * (Pool *).sizeof);
-            newpooltable[i] = pool;
-
-            pooltable = newpooltable;
-            npools = newnpools;
+            p.Dtor();
+            return null;
+        }
 
 
-            minAddr = pooltable[0].baseAddr;
-            maxAddr = pooltable[npools - 1].topAddr;
+        Pool* pool = pools.insert_sorted(p);
+        if (pool)
+        {
+            minAddr = pools[0].baseAddr;
+            maxAddr = pools[pools.length - 1].topAddr;
         }
         return pool;
         }
         return pool;
-
-      Lerr:
-        pool.Dtor();
-        cstdlib.free(pool);
-        return null;
     }
 
 
     }
 
 
@@ -2087,9 +1842,9 @@ struct Gcx
         byte*  p;
         byte*  ptop;
 
         byte*  p;
         byte*  ptop;
 
-        for (n = 0; n < npools; n++)
+        for (n = 0; n < pools.length; n++)
         {
         {
-            pool = pooltable[n];
+            pool = pools[n];
             pn = pool.allocPages(1);
             if (pn != OPFAIL)
                 goto L1;
             pn = pool.allocPages(1);
             if (pn != OPFAIL)
                 goto L1;
@@ -2172,7 +1927,6 @@ struct Gcx
                             pool.scan.set(biti);
                             changes = 1;
                         }
                             pool.scan.set(biti);
                             changes = 1;
                         }
-                        log_parent(sentinel_add(pool.baseAddr + biti * 16), sentinel_add(pbot));
                     }
                 }
             }
                     }
                 }
             }
@@ -2284,9 +2038,9 @@ struct Gcx
         size_cache = 0;
 
         anychanges = 0;
         size_cache = 0;
 
         anychanges = 0;
-        for (n = 0; n < npools; n++)
+        for (n = 0; n < pools.length; n++)
         {
         {
-            pool = pooltable[n];
+            pool = pools[n];
             pool.mark.zero();
             pool.scan.zero();
             pool.freebits.zero();
             pool.mark.zero();
             pool.scan.zero();
             pool.freebits.zero();
@@ -2303,9 +2057,9 @@ struct Gcx
             }
         }
 
             }
         }
 
-        for (n = 0; n < npools; n++)
+        for (n = 0; n < pools.length; n++)
         {
         {
-            pool = pooltable[n];
+            pool = pools[n];
             pool.mark.copy(&pool.freebits);
         }
 
             pool.mark.copy(&pool.freebits);
         }
 
@@ -2317,14 +2071,14 @@ struct Gcx
             thread_scanAll( &mark, stackTop );
         }
 
             thread_scanAll( &mark, stackTop );
         }
 
-        // Scan roots[]
+        // Scan roots
         debug(COLLECT_PRINTF) printf("scan roots[]\n");
         debug(COLLECT_PRINTF) printf("scan roots[]\n");
-        mark(roots, roots + nroots);
+        mark(roots.ptr, roots.ptr + roots.length);
 
 
-        // Scan ranges[]
+        // Scan ranges
         debug(COLLECT_PRINTF) printf("scan ranges[]\n");
         //log++;
         debug(COLLECT_PRINTF) printf("scan ranges[]\n");
         //log++;
-        for (n = 0; n < nranges; n++)
+        for (n = 0; n < ranges.length; n++)
         {
             debug(COLLECT_PRINTF) printf("\t%x .. %x\n", ranges[n].pbot, ranges[n].ptop);
             mark(ranges[n].pbot, ranges[n].ptop);
         {
             debug(COLLECT_PRINTF) printf("\t%x .. %x\n", ranges[n].pbot, ranges[n].ptop);
             mark(ranges[n].pbot, ranges[n].ptop);
@@ -2335,13 +2089,13 @@ struct Gcx
         while (anychanges)
         {
             anychanges = 0;
         while (anychanges)
         {
             anychanges = 0;
-            for (n = 0; n < npools; n++)
+            for (n = 0; n < pools.length; n++)
             {
                 uint *bbase;
                 uint *b;
                 uint *btop;
 
             {
                 uint *bbase;
                 uint *b;
                 uint *btop;
 
-                pool = pooltable[n];
+                pool = pools[n];
 
                 bbase = pool.scan.base();
                 btop = bbase + pool.scan.nwords;
 
                 bbase = pool.scan.base();
                 btop = bbase + pool.scan.nwords;
@@ -2401,9 +2155,9 @@ struct Gcx
         debug(COLLECT_PRINTF) printf("\tfree'ing\n");
         size_t freedpages = 0;
         size_t freed = 0;
         debug(COLLECT_PRINTF) printf("\tfree'ing\n");
         size_t freedpages = 0;
         size_t freed = 0;
-        for (n = 0; n < npools; n++)
+        for (n = 0; n < pools.length; n++)
         {
         {
-            pool = pooltable[n];
+            pool = pools[n];
             uint*  bbase = pool.mark.base();
             size_t pn;
             for (pn = 0; pn < pool.npages; pn++, bbase += PAGESIZE / (32 * 16))
             uint*  bbase = pool.mark.base();
             size_t pn;
             for (pn = 0; pn < pool.npages; pn++, bbase += PAGESIZE / (32 * 16))
@@ -2431,9 +2185,8 @@ struct Gcx
                             gcx.clrBits(pool, biti, BlkAttr.ALL_BITS);
 
                             List *list = cast(List *)p;
                             gcx.clrBits(pool, biti, BlkAttr.ALL_BITS);
 
                             List *list = cast(List *)p;
-                            log_free(sentinel_add(list));
 
 
-                            debug (MEMSTOMP) cstring.memset(p, 0xF3, size);
+                            debug (MEMSTOMP) memset(p, 0xF3, size);
                         }
                         pool.pagetable[pn] = B_FREE;
                         freed += PAGESIZE;
                         }
                         pool.pagetable[pn] = B_FREE;
                         freed += PAGESIZE;
@@ -2452,9 +2205,8 @@ struct Gcx
                             clrBits(pool, biti, BlkAttr.ALL_BITS);
 
                             List *list = cast(List *)p;
                             clrBits(pool, biti, BlkAttr.ALL_BITS);
 
                             List *list = cast(List *)p;
-                            log_free(sentinel_add(list));
 
 
-                            debug (MEMSTOMP) cstring.memset(p, 0xF3, size);
+                            debug (MEMSTOMP) memset(p, 0xF3, size);
 
                             freed += size;
                         }
 
                             freed += size;
                         }
@@ -2472,10 +2224,9 @@ struct Gcx
                         clrBits(pool, biti, BlkAttr.ALL_BITS);
 
                         debug(COLLECT_PRINTF) printf("\tcollecting big %x\n", p);
                         clrBits(pool, biti, BlkAttr.ALL_BITS);
 
                         debug(COLLECT_PRINTF) printf("\tcollecting big %x\n", p);
-                        log_free(sentinel_add(p));
                         pool.pagetable[pn] = B_FREE;
                         freedpages++;
                         pool.pagetable[pn] = B_FREE;
                         freedpages++;
-                        debug (MEMSTOMP) cstring.memset(p, 0xF3, PAGESIZE);
+                        debug (MEMSTOMP) memset(p, 0xF3, PAGESIZE);
                         while (pn + 1 < pool.npages && pool.pagetable[pn + 1] == B_PAGEPLUS)
                         {
                             pn++;
                         while (pn + 1 < pool.npages && pool.pagetable[pn + 1] == B_PAGEPLUS)
                         {
                             pn++;
@@ -2485,7 +2236,7 @@ struct Gcx
                             debug (MEMSTOMP)
                             {
                                 p += PAGESIZE;
                             debug (MEMSTOMP)
                             {
                                 p += PAGESIZE;
-                                cstring.memset(p, 0xF3, PAGESIZE);
+                                memset(p, 0xF3, PAGESIZE);
                             }
                         }
                     }
                             }
                         }
                     }
@@ -2499,9 +2250,9 @@ struct Gcx
         // Free complete pages, rebuild free list
         debug(COLLECT_PRINTF) printf("\tfree complete pages\n");
         size_t recoveredpages = 0;
         // Free complete pages, rebuild free list
         debug(COLLECT_PRINTF) printf("\tfree complete pages\n");
         size_t recoveredpages = 0;
-        for (n = 0; n < npools; n++)
+        for (n = 0; n < pools.length; n++)
         {
         {
-            pool = pooltable[n];
+            pool = pools[n];
             for (size_t pn = 0; pn < pool.npages; pn++)
             {
                 Bins   bin = cast(Bins)pool.pagetable[pn];
             for (size_t pn = 0; pn < pool.npages; pn++)
             {
                 Bins   bin = cast(Bins)pool.pagetable[pn];
@@ -2544,7 +2295,7 @@ struct Gcx
         }
 
         debug(COLLECT_PRINTF) printf("recovered pages = %d\n", recoveredpages);
         }
 
         debug(COLLECT_PRINTF) printf("recovered pages = %d\n", recoveredpages);
-        debug(COLLECT_PRINTF) printf("\tfree'd %u bytes, %u pages from %u pools\n", freed, freedpages, npools);
+        debug(COLLECT_PRINTF) printf("\tfree'd %u bytes, %u pages from %u pools\n", freed, freedpages, pools.length);
 
         return freedpages + recoveredpages;
     }
 
         return freedpages + recoveredpages;
     }
@@ -2621,111 +2372,6 @@ struct Gcx
 //            pool.nomove.clear(biti);
     }
 
 //            pool.nomove.clear(biti);
     }
 
-
-    /***** Leak Detector ******/
-
-
-    debug (LOGGING)
-    {
-        LogArray current;
-        LogArray prev;
-
-
-        void log_init()
-        {
-            current.reserve(1000);
-            prev.reserve(1000);
-        }
-
-
-        void log_malloc(void *p, size_t size)
-        {
-            Log log;
-
-            log.p = p;
-            log.size = size;
-            log.line = GC.line;
-            log.file = GC.file;
-            log.parent = null;
-
-            GC.line = 0;
-            GC.file = null;
-
-            current.push(log);
-        }
-
-
-        void log_free(void *p)
-        {
-            size_t i;
-
-            i = current.find(p);
-            if (i != OPFAIL)
-                current.remove(i);
-        }
-
-
-        void log_collect()
-        {
-            // Print everything in current that is not in prev
-            size_t used = 0;
-            for (size_t i = 0; i < current.dim; i++)
-            {
-                size_t j;
-
-                j = prev.find(current.data[i].p);
-                if (j == OPFAIL)
-                    current.data[i].print();
-                else
-                    used++;
-            }
-
-            for (size_t i = 0; i < current.dim; i++)
-            {
-                void *p;
-                size_t j;
-
-                p = current.data[i].p;
-                if (!findPool(current.data[i].parent))
-                {
-                    j = prev.find(current.data[i].p);
-                    current.data[i].print();
-                }
-            }
-
-            prev.copy(&current);
-        }
-
-
-        void log_parent(void *p, void *parent)
-        {
-            size_t i;
-
-            i = current.find(p);
-            if (i == OPFAIL)
-            {
-                Pool *pool;
-                pool = findPool(p);
-                assert(pool);
-                size_t offset = cast(size_t)(p - pool.baseAddr);
-                size_t biti;
-                size_t pn = offset / PAGESIZE;
-                Bins bin = cast(Bins)pool.pagetable[pn];
-                biti = (offset & notbinsize[bin]);
-            }
-            else
-                current.data[i].parent = parent;
-        }
-
-    }
-    else
-    {
-        void log_init() { }
-        void log_malloc(void *p, size_t size) { }
-        void log_free(void *p) { }
-        void log_collect() { }
-        void log_parent(void *p, void *parent) { }
-    }
 }
 
 
 }
 
 
@@ -2771,7 +2417,7 @@ struct Pool
         pagetable = cast(ubyte*) cstdlib.malloc(npages);
         if (!pagetable)
             onOutOfMemoryError();
         pagetable = cast(ubyte*) cstdlib.malloc(npages);
         if (!pagetable)
             onOutOfMemoryError();
-        cstring.memset(pagetable, B_FREE, npages);
+        memset(pagetable, B_FREE, npages);
 
         this.npages = npages;
     }
 
         this.npages = npages;
     }
@@ -2793,6 +2439,7 @@ struct Pool
             baseAddr = null;
             topAddr = null;
         }
             baseAddr = null;
             topAddr = null;
         }
+        // See Gcx.Dtor() for the rationale of the null check.
         if (pagetable)
             cstdlib.free(pagetable);
 
         if (pagetable)
             cstdlib.free(pagetable);
 
@@ -2859,19 +2506,19 @@ struct Pool
      */
     void freePages(size_t pagenum, size_t npages)
     {
      */
     void freePages(size_t pagenum, size_t npages)
     {
-        cstring.memset(&pagetable[pagenum], B_FREE, npages);
+        memset(&pagetable[pagenum], B_FREE, npages);
     }
 
 
     /**
     }
 
 
     /**
-     * Used for sorting pooltable[]
+     * Used for sorting pools
      */
      */
-    int opCmp(Pool *p2)
+    int opCmp(in Pool other)
     {
     {
-        if (baseAddr < p2.baseAddr)
+        if (baseAddr < other.baseAddr)
             return -1;
         else
             return -1;
         else
-        return cast(int)(baseAddr > p2.baseAddr);
+        return cast(int)(baseAddr > other.baseAddr);
     }
 }
 
     }
 }
 
@@ -2944,3 +2591,5 @@ else
     }
 }
 
     }
 }
 
+
+// vim: set et sw=4 sts=4 :