X-Git-Url: https://git.llucax.com/software/dgc/cdgc.git/blobdiff_plain/62b4073393f1d66e88322376627c8bef7b27f81d..e74b77edc55c73d1f1656131a645eed30a59727f:/rt/gc/cdgc/gc.d diff --git a/rt/gc/cdgc/gc.d b/rt/gc/cdgc/gc.d index 151d28b..96c6a86 100644 --- a/rt/gc/cdgc/gc.d +++ b/rt/gc/cdgc/gc.d @@ -50,6 +50,7 @@ import opts = rt.gc.cdgc.opts; 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 @@ -307,6 +308,8 @@ BlkInfo getInfo(void* 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)) { @@ -398,7 +401,7 @@ void minimize() { size_t n; size_t pn; - Pool* pool; + Pool* pool; 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; - uint changes = 0; + bool changes = false; 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); - size_t bit_i; + size_t bit_i = void; 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) - bit_i = (offset & notbinsize[bin]) >> 4; + bit_i = (offset & notbinsize[bin]) / 16; 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); } - else - { - // Don't mark bits in B_FREE pages + else // Don't mark bits in B_FREE pages 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)) { @@ -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); - changes = 1; + changes = true; } } } @@ -786,6 +787,7 @@ size_t fullcollect(void *stackTop) 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) { @@ -824,9 +826,6 @@ void mark(void *stackTop) { 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++) { @@ -972,6 +971,8 @@ size_t sweep() { // 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++) @@ -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) { - if (pool.finals.nbits && pool.finals.testClear(bit_i)) { + if (pool.finals.testClear(bit_i)) { 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 - 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); - List *list = cast(List *)p; - 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); - if (pool.finals.nbits && pool.finals.testClear(bit_i)) { + if (pool.finals.testClear(bit_i)) { 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 - 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); - List *list = cast(List *)p; - 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)); - 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 @@ -1155,14 +1152,11 @@ in 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; -// if (pool.nomove.nbits && -// pool.nomove.test(bit_i)) +// if (pool.nomove.test(bit_i)) // attrs |= BlkAttr.NO_MOVE; return attrs; } @@ -1180,8 +1174,6 @@ body { if (mask & BlkAttr.FINALIZE) { - if (!pool.finals.nbits) - pool.finals.alloc(pool.mark.nbits); pool.finals.set(bit_i); } if (mask & BlkAttr.NO_SCAN) @@ -1207,7 +1199,7 @@ in } 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); @@ -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 + // TODO: hint allocPage() to use the pool we just created 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); + 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**)( - 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; @@ -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); + 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**)( - blk_base_addr + - (PAGESIZE * newsz) - + blk_base_addr + new_blk_size - 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; + // 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; @@ -1615,11 +1618,13 @@ private void free(void *p) 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 - List *list = cast(List*)p; + List* list = cast(List*) p; 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 - 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); } @@ -1784,7 +1787,7 @@ private GCStats getStats() for (n = 0; n < B_PAGE; n++) { - for (List *list = gc.free_list[n]; list; list = list.next) + for (List* list = gc.free_list[n]; list; list = list.next) flsize += binsize[n]; } @@ -1895,10 +1898,18 @@ struct Pool 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) @@ -1915,7 +1926,6 @@ struct Pool npages = 0; poolsize = 0; } - //assert(baseAddr); topAddr = baseAddr + poolsize; size_t nbits = cast(size_t)poolsize / 16;