X-Git-Url: https://git.llucax.com/software/dgc/cdgc.git/blobdiff_plain/b5e1601adc7b579e9d2366aa2529b07ee6f47fe3..27b5b707bcd280cd2cc4e2a2a5cc17eb4e06347a:/rt/gc/cdgc/gc.d?ds=sidebyside diff --git a/rt/gc/cdgc/gc.d b/rt/gc/cdgc/gc.d index 267b42f..3a925fc 100644 --- a/rt/gc/cdgc/gc.d +++ b/rt/gc/cdgc/gc.d @@ -264,26 +264,28 @@ bool Invariant() * Return null if not in a Pool. * Assume pools is sorted. */ -Pool *findPool(void *p) +Pool* findPool(void* p) { - if (p >= gc.min_addr && p < gc.max_addr) - { - if (gc.pools.length == 1) - { - return gc.pools[0]; - } - - for (size_t i = 0; i < gc.pools.length; i++) - { - Pool* pool = gc.pools[i]; - if (p < pool.topAddr) - { - if (pool.baseAddr <= p) - return pool; - break; - } - } + if (p < gc.min_addr || p >= gc.max_addr) + return null; + if (gc.pools.length == 0) + return null; + if (gc.pools.length == 1) + return gc.pools[0]; + /// The pooltable[] is sorted by address, so do a binary search + size_t low = 0; + size_t high = gc.pools.length - 1; + while (low <= high) { + size_t mid = (low + high) / 2; + auto pool = gc.pools[mid]; + if (p < pool.baseAddr) + high = mid - 1; + else if (p >= pool.topAddr) + low = mid + 1; + else + return pool; } + // Not found return null; } @@ -302,8 +304,20 @@ BlkInfo getInfo(void* p) info.base = pool.findBase(p); info.size = pool.findSize(info.base); info.attr = getAttr(pool, cast(size_t)(info.base - pool.baseAddr) / 16u); - if (!opts.options.conservative && !(info.attr & BlkAttr.NO_SCAN)) + if (has_pointermap(info.attr)) { info.size -= size_t.sizeof; // PointerMap bitmask + // Points to the PointerMap bitmask pointer, not user data + if (p >= (info.base + info.size)) { + return BlkInfo.init; + } + } + if (opts.options.sentinel) { + info.base = sentinel_add(info.base); + // points to sentinel data, not user data + if (p < info.base || p >= sentinel_post(info.base)) + return BlkInfo.init; + info.size -= SENTINEL_EXTRA; + } return info; } @@ -603,12 +617,14 @@ void mark(void *pbot, void *ptop, size_t* pm_bitmask) size_t type_size = pm_bitmask[0]; size_t* pm_bits = pm_bitmask + 1; + bool has_type_info = type_size != 1 || pm_bits[0] != 1 || pm_bits[1] != 0; //printf("marking range: %p -> %p\n", pbot, ptop); for (; p1 + type_size <= p2; p1 += type_size) { for (size_t n = 0; n < type_size; n++) { // scan bit set for this word - if (!(pm_bits[n / BITS_PER_WORD] & (1 << (n % BITS_PER_WORD)))) + if (has_type_info && + !(pm_bits[n / BITS_PER_WORD] & (1 << (n % BITS_PER_WORD)))) continue; void* p = *(p1 + n); @@ -912,6 +928,7 @@ size_t fullcollect(void *stackTop) for (n = 0; n < gc.pools.length; n++) { pool = gc.pools[n]; + pool.clear_cache(); uint* bbase = pool.mark.base(); size_t pn; for (pn = 0; pn < pool.npages; pn++, bbase += PAGESIZE / (32 * 16)) @@ -1815,6 +1832,15 @@ struct Pool size_t npages; ubyte* pagetable; + /// Cache for findSize() + size_t cached_size; + void* cached_ptr; + + void clear_cache() + { + this.cached_ptr = null; + this.cached_size = 0; + } void initialize(size_t npages) { @@ -1971,10 +1997,15 @@ struct Pool Bins bin = cast(Bins)this.pagetable[pagenum]; if (bin != B_PAGE) return binsize[bin]; - for (size_t i = pagenum + 1; i < this.npages; i++) + if (this.cached_ptr == p) + return this.cached_size; + size_t i = pagenum + 1; + for (; i < this.npages; i++) if (this.pagetable[i] != B_PAGEPLUS) - return (i - pagenum) * PAGESIZE; - return (this.npages - pagenum) * PAGESIZE; + break; + this.cached_ptr = p; + this.cached_size = (i - pagenum) * PAGESIZE; + return this.cached_size; }