]> git.llucax.com Git - software/dgc/cdgc.git/blobdiff - rt/gc/cdgc/gc.d
Avoid output duplication because of FILE* buffers
[software/dgc/cdgc.git] / rt / gc / cdgc / gc.d
index 151d28b6860bce5a38c6d3b4eafb8df0d7e53b68..96c6a86360d24277f0456ea9038f17580f90864d 100644 (file)
@@ -50,6 +50,7 @@ import opts = rt.gc.cdgc.opts;
 
 import cstdlib = tango.stdc.stdlib;
 import cstring = tango.stdc.string;
 
 import cstdlib = tango.stdc.stdlib;
 import cstring = tango.stdc.string;
+import cstdio = tango.stdc.stdio;
 
 /*
  * This is a small optimization that proved it's usefulness. For small chunks
 
 /*
  * This is a small optimization that proved it's usefulness. For small chunks
@@ -307,6 +308,8 @@ BlkInfo getInfo(void* p)
         return BlkInfo.init;
     BlkInfo info;
     info.base = pool.findBase(p);
         return BlkInfo.init;
     BlkInfo info;
     info.base = pool.findBase(p);
+    if (info.base is null)
+        return BlkInfo.init;
     info.size = pool.findSize(info.base);
     info.attr = getAttr(pool, cast(size_t)(info.base - pool.baseAddr) / 16u);
     if (has_pointermap(info.attr)) {
     info.size = pool.findSize(info.base);
     info.attr = getAttr(pool, cast(size_t)(info.base - pool.baseAddr) / 16u);
     if (has_pointermap(info.attr)) {
@@ -398,7 +401,7 @@ void minimize()
 {
     size_t n;
     size_t pn;
 {
     size_t n;
     size_t pn;
-    Pool*  pool;
+    Pool* pool;
 
     for (n = 0; n < gc.pools.length; n++)
     {
 
     for (n = 0; n < gc.pools.length; n++)
     {
@@ -615,7 +618,7 @@ void mark_range(void *pbot, void *ptop, size_t* pm_bitmask)
     void **p1 = cast(void **)pbot;
     void **p2 = cast(void **)ptop;
     size_t pcache = 0;
     void **p1 = cast(void **)pbot;
     void **p2 = cast(void **)ptop;
     size_t pcache = 0;
-    uint changes = 0;
+    bool changes = false;
 
     size_t type_size = pm_bitmask[0];
     size_t* pm_bits = pm_bitmask + 1;
 
     size_t type_size = pm_bitmask[0];
     size_t* pm_bits = pm_bitmask + 1;
@@ -641,13 +644,17 @@ void mark_range(void *pbot, void *ptop, size_t* pm_bitmask)
             if (pool)
             {
                 size_t offset = cast(size_t)(p - pool.baseAddr);
             if (pool)
             {
                 size_t offset = cast(size_t)(p - pool.baseAddr);
-                size_t bit_i;
+                size_t bit_i = void;
                 size_t pn = offset / PAGESIZE;
                 Bins   bin = cast(Bins)pool.pagetable[pn];
 
                 size_t pn = offset / PAGESIZE;
                 Bins   bin = cast(Bins)pool.pagetable[pn];
 
+                // Cache B_PAGE, B_PAGEPLUS and B_FREE lookups
+                if (bin >= B_PAGE)
+                    pcache = cast(size_t)p & ~(PAGESIZE-1);
+
                 // Adjust bit to be at start of allocated memory block
                 if (bin <= B_PAGE)
                 // Adjust bit to be at start of allocated memory block
                 if (bin <= B_PAGE)
-                    bit_i = (offset & notbinsize[bin]) >> 4;
+                    bit_i = (offset & notbinsize[bin]) / 16;
                 else if (bin == B_PAGEPLUS)
                 {
                     do
                 else if (bin == B_PAGEPLUS)
                 {
                     do
@@ -657,14 +664,8 @@ void mark_range(void *pbot, void *ptop, size_t* pm_bitmask)
                     while (cast(Bins)pool.pagetable[pn] == B_PAGEPLUS);
                     bit_i = pn * (PAGESIZE / 16);
                 }
                     while (cast(Bins)pool.pagetable[pn] == B_PAGEPLUS);
                     bit_i = pn * (PAGESIZE / 16);
                 }
-                else
-                {
-                    // Don't mark bits in B_FREE pages
+                else // Don't mark bits in B_FREE pages
                     continue;
                     continue;
-                }
-
-                if (bin >= B_PAGE) // Cache B_PAGE and B_PAGEPLUS lookups
-                    pcache = cast(size_t)p & ~(PAGESIZE-1);
 
                 if (!pool.mark.test(bit_i))
                 {
 
                 if (!pool.mark.test(bit_i))
                 {
@@ -672,7 +673,7 @@ void mark_range(void *pbot, void *ptop, size_t* pm_bitmask)
                     if (!pool.noscan.test(bit_i))
                     {
                         pool.scan.set(bit_i);
                     if (!pool.noscan.test(bit_i))
                     {
                         pool.scan.set(bit_i);
-                        changes = 1;
+                        changes = true;
                     }
                 }
             }
                     }
                 }
             }
@@ -786,6 +787,7 @@ size_t fullcollect(void *stackTop)
     gc.stats.world_stopped();
 
     if (opts.options.fork) {
     gc.stats.world_stopped();
 
     if (opts.options.fork) {
+        cstdio.fflush(null); // avoid duplicated FILE* output
         os.pid_t child_pid = os.fork();
         assert (child_pid != -1); // don't accept errors in non-release mode
         switch (child_pid) {
         os.pid_t child_pid = os.fork();
         assert (child_pid != -1); // don't accept errors in non-release mode
         switch (child_pid) {
@@ -824,9 +826,6 @@ void mark(void *stackTop)
 {
     debug(COLLECT_PRINTF) printf("\tmark()\n");
 
 {
     debug(COLLECT_PRINTF) printf("\tmark()\n");
 
-    gc.p_cache = null;
-    gc.size_cache = 0;
-
     gc.any_changes = false;
     for (size_t n = 0; n < gc.pools.length; n++)
     {
     gc.any_changes = false;
     for (size_t n = 0; n < gc.pools.length; n++)
     {
@@ -972,6 +971,8 @@ size_t sweep()
 {
     // Free up everything not marked
     debug(COLLECT_PRINTF) printf("\tsweep\n");
 {
     // Free up everything not marked
     debug(COLLECT_PRINTF) printf("\tsweep\n");
+    gc.p_cache = null;
+    gc.size_cache = 0;
     size_t freedpages = 0;
     size_t freed = 0;
     for (size_t n = 0; n < gc.pools.length; n++)
     size_t freedpages = 0;
     size_t freed = 0;
     for (size_t n = 0; n < gc.pools.length; n++)
@@ -1001,16 +1002,14 @@ version(none) // BUG: doesn't work because freebits() must also be cleared
                 {
                     for (; p < ptop; p += size, bit_i += bit_stride)
                     {
                 {
                     for (; p < ptop; p += size, bit_i += bit_stride)
                     {
-                        if (pool.finals.nbits && pool.finals.testClear(bit_i)) {
+                        if (pool.finals.testClear(bit_i)) {
                             if (opts.options.sentinel)
                             if (opts.options.sentinel)
-                                rt_finalize(cast(List *)sentinel_add(p), false/*gc.no_stack > 0*/);
+                                rt_finalize(sentinel_add(p), false/*gc.no_stack > 0*/);
                             else
                             else
-                                rt_finalize(cast(List *)p, false/*gc.no_stack > 0*/);
+                                rt_finalize(p, false/*gc.no_stack > 0*/);
                         }
                         clrAttr(pool, bit_i, BlkAttr.ALL_BITS);
 
                         }
                         clrAttr(pool, bit_i, BlkAttr.ALL_BITS);
 
-                        List *list = cast(List *)p;
-
                         if (opts.options.mem_stomp)
                             memset(p, 0xF3, size);
                     }
                         if (opts.options.mem_stomp)
                             memset(p, 0xF3, size);
                     }
@@ -1027,16 +1026,14 @@ version(none) // BUG: doesn't work because freebits() must also be cleared
                             sentinel_Invariant(sentinel_add(p));
 
                         pool.freebits.set(bit_i);
                             sentinel_Invariant(sentinel_add(p));
 
                         pool.freebits.set(bit_i);
-                        if (pool.finals.nbits && pool.finals.testClear(bit_i)) {
+                        if (pool.finals.testClear(bit_i)) {
                             if (opts.options.sentinel)
                             if (opts.options.sentinel)
-                                rt_finalize(cast(List *)sentinel_add(p), false/*gc.no_stack > 0*/);
+                                rt_finalize(sentinel_add(p), false/*gc.no_stack > 0*/);
                             else
                             else
-                                rt_finalize(cast(List *)p, false/*gc.no_stack > 0*/);
+                                rt_finalize(p, false/*gc.no_stack > 0*/);
                         }
                         clrAttr(pool, bit_i, BlkAttr.ALL_BITS);
 
                         }
                         clrAttr(pool, bit_i, BlkAttr.ALL_BITS);
 
-                        List *list = cast(List *)p;
-
                         if (opts.options.mem_stomp)
                             memset(p, 0xF3, size);
 
                         if (opts.options.mem_stomp)
                             memset(p, 0xF3, size);
 
@@ -1052,7 +1049,7 @@ version(none) // BUG: doesn't work because freebits() must also be cleared
                     byte *p = pool.baseAddr + pn * PAGESIZE;
                     if (opts.options.sentinel)
                         sentinel_Invariant(sentinel_add(p));
                     byte *p = pool.baseAddr + pn * PAGESIZE;
                     if (opts.options.sentinel)
                         sentinel_Invariant(sentinel_add(p));
-                    if (pool.finals.nbits && pool.finals.testClear(bit_i)) {
+                    if (pool.finals.testClear(bit_i)) {
                         if (opts.options.sentinel)
                             rt_finalize(sentinel_add(p), false/*gc.no_stack > 0*/);
                         else
                         if (opts.options.sentinel)
                             rt_finalize(sentinel_add(p), false/*gc.no_stack > 0*/);
                         else
@@ -1155,14 +1152,11 @@ in
 body
 {
     uint attrs;
 body
 {
     uint attrs;
-
-    if (pool.finals.nbits &&
-        pool.finals.test(bit_i))
+    if (pool.finals.test(bit_i))
         attrs |= BlkAttr.FINALIZE;
     if (pool.noscan.test(bit_i))
         attrs |= BlkAttr.NO_SCAN;
         attrs |= BlkAttr.FINALIZE;
     if (pool.noscan.test(bit_i))
         attrs |= BlkAttr.NO_SCAN;
-//        if (pool.nomove.nbits &&
-//            pool.nomove.test(bit_i))
+//        if (pool.nomove.test(bit_i))
 //            attrs |= BlkAttr.NO_MOVE;
     return attrs;
 }
 //            attrs |= BlkAttr.NO_MOVE;
     return attrs;
 }
@@ -1180,8 +1174,6 @@ body
 {
     if (mask & BlkAttr.FINALIZE)
     {
 {
     if (mask & BlkAttr.FINALIZE)
     {
-        if (!pool.finals.nbits)
-            pool.finals.alloc(pool.mark.nbits);
         pool.finals.set(bit_i);
     }
     if (mask & BlkAttr.NO_SCAN)
         pool.finals.set(bit_i);
     }
     if (mask & BlkAttr.NO_SCAN)
@@ -1207,7 +1199,7 @@ in
 }
 body
 {
 }
 body
 {
-    if (mask & BlkAttr.FINALIZE && pool.finals.nbits)
+    if (mask & BlkAttr.FINALIZE)
         pool.finals.clear(bit_i);
     if (mask & BlkAttr.NO_SCAN)
         pool.noscan.clear(bit_i);
         pool.finals.clear(bit_i);
     if (mask & BlkAttr.NO_SCAN)
         pool.noscan.clear(bit_i);
@@ -1294,6 +1286,7 @@ private void *malloc(size_t size, uint attrs, size_t* pm_bitmask)
             if (!gc.free_list[bin] && !allocPage(bin))
             {
                 newPool(1);         // allocate new pool to find a new page
             if (!gc.free_list[bin] && !allocPage(bin))
             {
                 newPool(1);         // allocate new pool to find a new page
+                // TODO: hint allocPage() to use the pool we just created
                 int result = allocPage(bin);
                 if (!result)
                     onOutOfMemoryError();
                 int result = allocPage(bin);
                 if (!result)
                     onOutOfMemoryError();
@@ -1437,10 +1430,13 @@ private void *realloc(void *p, size_t size, uint attrs,
                         memset(p + size - pm_bitmask_size, 0xF2,
                                 blk_size - size - pm_bitmask_size);
                     pool.freePages(pagenum + newsz, psz - newsz);
                         memset(p + size - pm_bitmask_size, 0xF2,
                                 blk_size - size - pm_bitmask_size);
                     pool.freePages(pagenum + newsz, psz - newsz);
+                    auto new_blk_size = (PAGESIZE * newsz);
+                    // update the size cache, assuming that is very likely the
+                    // size of this block will be queried in the near future
+                    pool.update_cache(p, new_blk_size);
                     if (has_pm) {
                     if (has_pm) {
-                        auto end_of_blk = cast(size_t**)(
-                                blk_base_addr + (PAGESIZE * newsz) -
-                                pm_bitmask_size);
+                        auto end_of_blk = cast(size_t**)(blk_base_addr +
+                                new_blk_size - pm_bitmask_size);
                         *end_of_blk = pm_bitmask;
                     }
                     return p;
                         *end_of_blk = pm_bitmask;
                     }
                     return p;
@@ -1458,10 +1454,14 @@ private void *realloc(void *p, size_t size, uint attrs,
                                         - pm_bitmask_size);
                             memset(pool.pagetable + pagenum +
                                     psz, B_PAGEPLUS, newsz - psz);
                                         - pm_bitmask_size);
                             memset(pool.pagetable + pagenum +
                                     psz, B_PAGEPLUS, newsz - psz);
+                            auto new_blk_size = (PAGESIZE * newsz);
+                            // update the size cache, assuming that is very
+                            // likely the size of this block will be queried in
+                            // the near future
+                            pool.update_cache(p, new_blk_size);
                             if (has_pm) {
                                 auto end_of_blk = cast(size_t**)(
                             if (has_pm) {
                                 auto end_of_blk = cast(size_t**)(
-                                        blk_base_addr +
-                                        (PAGESIZE * newsz) -
+                                        blk_base_addr + new_blk_size -
                                         pm_bitmask_size);
                                 *end_of_blk = pm_bitmask;
                             }
                                         pm_bitmask_size);
                                 *end_of_blk = pm_bitmask;
                             }
@@ -1570,6 +1570,9 @@ body
     memset(pool.pagetable + pagenum + psz, B_PAGEPLUS, sz);
     gc.p_cache = null;
     gc.size_cache = 0;
     memset(pool.pagetable + pagenum + psz, B_PAGEPLUS, sz);
     gc.p_cache = null;
     gc.size_cache = 0;
+    // update the size cache, assuming that is very likely the size of this
+    // block will be queried in the near future
+    pool.update_cache(p, new_size);
 
     if (has_pm) {
         new_size -= size_t.sizeof;
 
     if (has_pm) {
         new_size -= size_t.sizeof;
@@ -1615,11 +1618,13 @@ private void free(void *p)
         if (opts.options.mem_stomp)
             memset(p, 0xF2, npages * PAGESIZE);
         pool.freePages(pagenum, npages);
         if (opts.options.mem_stomp)
             memset(p, 0xF2, npages * PAGESIZE);
         pool.freePages(pagenum, npages);
+        // just in case we were caching this pointer
+        pool.clear_cache(p);
     }
     else
     {
         // Add to free list
     }
     else
     {
         // Add to free list
-        List *list = cast(List*)p;
+        List* list = cast(List*) p;
 
         if (opts.options.mem_stomp)
             memset(p, 0xF2, binsize[bin]);
 
         if (opts.options.mem_stomp)
             memset(p, 0xF2, binsize[bin]);
@@ -1716,9 +1721,7 @@ private void checkNoSync(void *p)
             if (bin < B_PAGE)
             {
                 // Check that p is not on a free list
             if (bin < B_PAGE)
             {
                 // Check that p is not on a free list
-                List *list;
-
-                for (list = gc.free_list[bin]; list; list = list.next)
+                for (List* list = gc.free_list[bin]; list; list = list.next)
                 {
                     assert(cast(void*)list != p);
                 }
                 {
                     assert(cast(void*)list != p);
                 }
@@ -1784,7 +1787,7 @@ private GCStats getStats()
 
     for (n = 0; n < B_PAGE; n++)
     {
 
     for (n = 0; n < B_PAGE; n++)
     {
-        for (List *list = gc.free_list[n]; list; list = list.next)
+        for (Listlist = gc.free_list[n]; list; list = list.next)
             flsize += binsize[n];
     }
 
             flsize += binsize[n];
     }
 
@@ -1895,10 +1898,18 @@ struct Pool
     size_t cached_size;
     void* cached_ptr;
 
     size_t cached_size;
     void* cached_ptr;
 
-    void clear_cache()
+    void clear_cache(void* ptr = null)
+    {
+        if (ptr is null || ptr is this.cached_ptr) {
+            this.cached_ptr = null;
+            this.cached_size = 0;
+        }
+    }
+
+    void update_cache(void* ptr, size_t size)
     {
     {
-        this.cached_ptr = null;
-        this.cached_size = 0;
+        this.cached_ptr = ptr;
+        this.cached_size = size;
     }
 
     void initialize(size_t npages)
     }
 
     void initialize(size_t npages)
@@ -1915,7 +1926,6 @@ struct Pool
             npages = 0;
             poolsize = 0;
         }
             npages = 0;
             poolsize = 0;
         }
-        //assert(baseAddr);
         topAddr = baseAddr + poolsize;
 
         size_t nbits = cast(size_t)poolsize / 16;
         topAddr = baseAddr + poolsize;
 
         size_t nbits = cast(size_t)poolsize / 16;