]> git.llucax.com Git - software/dgc/cdgc.git/blobdiff - rt/gc/cdgc/gc.d
Do a binary search in findPool()
[software/dgc/cdgc.git] / rt / gc / cdgc / gc.d
index 267b42f04ebe1adc066af955a1f43a1e670a29b1..1df824cdaf38ff5a3baa911f7a9076250d60c285 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;
 }
 
@@ -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,25 @@ 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++) {
+        size_t n = 0;
+        if (has_type_info) {
+            while (n < type_size && pm_bits[n / BITS_PER_WORD] == 0)
+                n += BITS_PER_WORD;
+            if (n < type_size && (pm_bits[n / BITS_PER_WORD] &
+                        ((1 << (BITS_PER_WORD / 2)) - 1)) == 0)
+                n += BITS_PER_WORD / 2;
+            else if (n < type_size && (pm_bits[n / BITS_PER_WORD] &
+                        ((1 << (BITS_PER_WORD / 4)) - 1)) == 0)
+                n += BITS_PER_WORD / 4;
+        }
+        for (; 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);