]> git.llucax.com Git - software/dgc/cdgc.git/blobdiff - rt/gc/cdgc/gc.d
Revert "Skip non-scanneable words in chunks"
[software/dgc/cdgc.git] / rt / gc / cdgc / gc.d
index b8008f11a9ae7b7c4fac48bbaf33c931a5af8a88..3a925fc40bf358a64ecdbde8985e3d932caf75da 100644 (file)
@@ -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;
 }
 
@@ -295,65 +297,26 @@ Pool *findPool(void *p)
 BlkInfo getInfo(void* p)
 {
     assert (p !is null);
-
-    Pool*   pool;
+    Pool* pool = findPool(p);
+    if (pool is null)
+        return BlkInfo.init;
     BlkInfo info;
-
-    pool = findPool(p);
-    if (pool)
-    {
-        size_t offset = cast(size_t)(p - pool.baseAddr);
-        size_t pn = offset / PAGESIZE;
-        Bins   bin = cast(Bins)pool.pagetable[pn];
-
-        ////////////////////////////////////////////////////////////////////
-        // findAddr
-        ////////////////////////////////////////////////////////////////////
-
-        if (bin <= B_PAGE)
-        {
-            info.base = pool.baseAddr + (offset & notbinsize[bin]);
-        }
-        else if (bin == B_PAGEPLUS)
-        {
-            do
-            {
-                --pn, offset -= PAGESIZE;
-            }
-            while (cast(Bins)pool.pagetable[pn] == B_PAGEPLUS);
-
-            info.base = pool.baseAddr + (offset & (offset.max ^ (PAGESIZE-1)));
-
-            // fix bin for use by size calc below
-            bin = cast(Bins)pool.pagetable[pn];
+    info.base = pool.findBase(p);
+    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 -= size_t.sizeof; // PointerMap bitmask
+        // Points to the PointerMap bitmask pointer, not user data
+        if (p >= (info.base + info.size)) {
+            return BlkInfo.init;
         }
-
-        ////////////////////////////////////////////////////////////////////
-        // findSize
-        ////////////////////////////////////////////////////////////////////
-
-        info.size = binsize[bin];
-        if (bin == B_PAGE)
-        {
-            ubyte* pt;
-            size_t i;
-
-            pt = &pool.pagetable[0];
-            for (i = pn + 1; i < pool.npages; i++)
-            {
-                if (pt[i] != B_PAGEPLUS)
-                    break;
-            }
-            info.size = (i - pn) * PAGESIZE;
-        }
-
-        ////////////////////////////////////////////////////////////////////
-        // getAttr
-        ////////////////////////////////////////////////////////////////////
-
-        info.attr = getAttr(pool, cast(size_t)(offset / 16));
-        if (!(info.attr & BlkAttr.NO_SCAN))
-            info.size -= (size_t*).sizeof;  // bitmask
+    }
+    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;
 }
@@ -654,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);
@@ -963,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))
@@ -1866,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)
     {
@@ -2022,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;
     }