]> 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 5cd59abdafe458635aee7b63445e87b402e48aea..1df824cdaf38ff5a3baa911f7a9076250d60c285 100644 (file)
@@ -99,32 +99,29 @@ package bool has_pointermap(uint attrs)
 
 private
 {
-
-    extern (C) void* rt_stackBottom();
-    extern (C) void* rt_stackTop();
-
-    extern (C) void rt_finalize( void* p, bool det = true );
-
     alias void delegate(Object) DEvent;
-    extern (C) void rt_attachDisposeEvent(Object h, DEvent e);
-    extern (C) bool rt_detachDisposeEvent(Object h, DEvent e);
-
-
     alias void delegate( void*, void* ) scanFn;
+    enum { OPFAIL = ~cast(size_t)0 }
 
-    extern (C) void rt_scanStaticData( scanFn scan );
-
-    extern (C) bool thread_needLock();
-    extern (C) void thread_suspendAll();
-    extern (C) void thread_resumeAll();
+    extern (C)
+    {
+        version (DigitalMars) version(OSX)
+            oid _d_osx_image_init();
 
-    extern (C) void thread_scanAll( scanFn fn, void* curStackTop = null );
+        void* rt_stackBottom();
+        void* rt_stackTop();
+        void rt_finalize( void* p, bool det = true );
+        void rt_attachDisposeEvent(Object h, DEvent e);
+        bool rt_detachDisposeEvent(Object h, DEvent e);
+        void rt_scanStaticData( scanFn scan );
 
-    extern (C) void onOutOfMemoryError();
+        void thread_init();
+        bool thread_needLock();
+        void thread_suspendAll();
+        void thread_resumeAll();
+        void thread_scanAll( scanFn fn, void* curStackTop = null );
 
-    enum
-    {
-        OPFAIL = ~cast(size_t)0
+        void onOutOfMemoryError();
     }
 }
 
@@ -267,105 +264,32 @@ 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;
-            }
-        }
-    }
-    return null;
-}
-
-
-/**
- * Find base address of block containing pointer p.
- * Returns null if not a gc'd pointer
- */
-void* findBase(void *p)
-{
-    Pool *pool;
-
-    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];
-
-        // Adjust bit to be at start of allocated memory block
-        if (bin <= B_PAGE)
-        {
-            return pool.baseAddr + (offset & notbinsize[bin]);
-        }
-        else if (bin == B_PAGEPLUS)
-        {
-            do
-            {
-                --pn, offset -= PAGESIZE;
-            } while (cast(Bins)pool.pagetable[pn] == B_PAGEPLUS);
-
-            return pool.baseAddr + (offset & (offset.max ^ (PAGESIZE-1)));
-        }
+    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
-        {
-            // we are in a B_FREE page
-            return null;
-        }
+            return pool;
     }
+    // Not found
     return null;
 }
 
 
-/**
- * Find size of pointer p.
- * Returns 0 if not a gc'd pointer
- */
-size_t findSize(void *p)
-{
-    Pool*  pool;
-    size_t size = 0;
-
-    pool = findPool(p);
-    if (pool)
-    {
-        size_t pagenum;
-        Bins   bin;
-
-        pagenum = cast(size_t)(p - pool.baseAddr) / PAGESIZE;
-        bin = cast(Bins)pool.pagetable[pagenum];
-        size = binsize[bin];
-        if (bin == B_PAGE)
-        {
-            ubyte* pt;
-            size_t i;
-
-            pt = &pool.pagetable[0];
-            for (i = pagenum + 1; i < pool.npages; i++)
-            {
-                if (pt[i] != B_PAGEPLUS)
-                    break;
-            }
-            size = (i - pagenum) * PAGESIZE;
-        }
-    }
-    return size;
-}
-
-
 /**
  * Determine the base address of the block containing p.  If p is not a gc
  * allocated pointer, return null.
@@ -373,65 +297,26 @@ size_t findSize(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];
-        }
-
-        ////////////////////////////////////////////////////////////////////
-        // 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;
+    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;
         }
-
-        ////////////////////////////////////////////////////////////////////
-        // 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;
 }
@@ -732,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);
@@ -1445,8 +1343,8 @@ private void *realloc(void *p, size_t size, uint attrs,
         else
             attrs = getAttr(pool, bit_i);
 
-        void* blk_base_addr = findBase(p);
-        size_t blk_size = findSize(p);
+        void* blk_base_addr = pool.findBase(p);
+        size_t blk_size = pool.findSize(p);
         bool has_pm = has_pointermap(attrs);
         size_t pm_bitmask_size = 0;
         if (has_pm) {
@@ -1575,8 +1473,8 @@ body
     auto bit_i = cast(size_t)(p - pool.baseAddr) / 16;
     uint attrs = getAttr(pool, bit_i);
 
-    void* blk_base_addr = findBase(p);
-    size_t blk_size = findSize(p);
+    void* blk_base_addr = pool.findBase(p);
+    size_t blk_size = pool.findSize(p);
     bool has_pm = has_pointermap(attrs);
     size_t* pm_bitmask = null;
     size_t pm_bitmask_size = 0;
@@ -1702,7 +1600,7 @@ private size_t sizeOf(void *p)
     auto biti = cast(size_t)(p - pool.baseAddr) / 16;
     uint attrs = getAttr(pool, biti);
 
-    size_t size = findSize(p);
+    size_t size = pool.findSize(p);
     size_t pm_bitmask_size = 0;
     if (has_pointermap(attrs))
         pm_bitmask_size = size_t.sizeof;
@@ -2066,6 +1964,47 @@ struct Pool
     }
 
 
+    /**
+     * Find base address of block containing pointer p.
+     * Returns null if the pointer doesn't belong to this pool
+     */
+    void* findBase(void *p)
+    {
+        size_t offset = cast(size_t)(p - this.baseAddr);
+        size_t pagenum = offset / PAGESIZE;
+        Bins bin = cast(Bins)this.pagetable[pagenum];
+        // Adjust bit to be at start of allocated memory block
+        if (bin <= B_PAGE)
+            return this.baseAddr + (offset & notbinsize[bin]);
+        if (bin == B_PAGEPLUS) {
+            do {
+                --pagenum, offset -= PAGESIZE;
+            } while (cast(Bins)this.pagetable[pagenum] == B_PAGEPLUS);
+            return this.baseAddr + (offset & (offset.max ^ (PAGESIZE-1)));
+        }
+        // we are in a B_FREE page
+        return null;
+    }
+
+
+    /**
+     * Find size of pointer p.
+     * Returns 0 if p doesn't belong to this pool if if it's block size is less
+     * than a PAGE.
+     */
+    size_t findSize(void *p)
+    {
+        size_t pagenum = cast(size_t)(p - this.baseAddr) / PAGESIZE;
+        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.pagetable[i] != B_PAGEPLUS)
+                return (i - pagenum) * PAGESIZE;
+        return (this.npages - pagenum) * PAGESIZE;
+    }
+
+
     /**
      * Used for sorting pools
      */
@@ -2125,29 +2064,27 @@ void *sentinel_sub(void *p)
 
 private int _termCleanupLevel=1;
 
+extern (C):
+
 /// sets the cleanup level done by gc
 /// 0: none
 /// 1: fullCollect
 /// 2: fullCollect ignoring stack roots (might crash daemonThreads)
 /// result !=0 if the value was invalid
-extern (C) int gc_setTermCleanupLevel(int cLevel){
+int gc_setTermCleanupLevel(int cLevel)
+{
     if (cLevel<0 || cLevel>2) return cLevel;
     _termCleanupLevel=cLevel;
     return 0;
 }
 
 /// returns the cleanup level done by gc
-extern (C) int gc_getTermCleanupLevel(){
+int gc_getTermCleanupLevel()
+{
     return _termCleanupLevel;
 }
 
-version (DigitalMars) version(OSX) {
-    extern(C) void _d_osx_image_init();
-}
-
-extern (C) void thread_init();
-
-extern (C) void gc_init()
+void gc_init()
 {
     scope (exit) assert (Invariant());
     gc = cast(GC*) cstdlib.calloc(1, GC.sizeof);
@@ -2161,7 +2098,7 @@ extern (C) void gc_init()
     thread_init();
 }
 
-extern (C) void gc_term()
+void gc_term()
 {
     assert (Invariant());
     if (_termCleanupLevel<1) {
@@ -2193,7 +2130,7 @@ extern (C) void gc_term()
     }
 }
 
-extern (C) void gc_enable()
+void gc_enable()
 {
     return locked!(void, () {
         assert (Invariant()); scope (exit) assert (Invariant());
@@ -2202,7 +2139,7 @@ extern (C) void gc_enable()
     })();
 }
 
-extern (C) void gc_disable()
+void gc_disable()
 {
     return locked!(void, () {
         assert (Invariant()); scope (exit) assert (Invariant());
@@ -2210,7 +2147,7 @@ extern (C) void gc_disable()
     })();
 }
 
-extern (C) void gc_collect()
+void gc_collect()
 {
     return locked!(void, () {
         assert (Invariant()); scope (exit) assert (Invariant());
@@ -2219,7 +2156,7 @@ extern (C) void gc_collect()
 }
 
 
-extern (C) void gc_minimize()
+void gc_minimize()
 {
     return locked!(void, () {
         assert (Invariant()); scope (exit) assert (Invariant());
@@ -2227,7 +2164,7 @@ extern (C) void gc_minimize()
     })();
 }
 
-extern (C) uint gc_getAttr( void* p )
+uint gc_getAttr(void* p)
 {
     if (p is null)
         return 0;
@@ -2241,7 +2178,7 @@ extern (C) uint gc_getAttr( void* p )
     })();
 }
 
-extern (C) uint gc_setAttr(void* p, uint attrs)
+uint gc_setAttr(void* p, uint attrs)
 {
     if (p is null)
         return 0;
@@ -2257,7 +2194,7 @@ extern (C) uint gc_setAttr(void* p, uint attrs)
     })();
 }
 
-extern (C) uint gc_clrAttr(void* p, uint attrs)
+uint gc_clrAttr(void* p, uint attrs)
 {
     if (p is null)
         return 0;
@@ -2273,7 +2210,7 @@ extern (C) uint gc_clrAttr(void* p, uint attrs)
     })();
 }
 
-extern (C) void* gc_malloc(size_t size, uint attrs = 0,
+void* gc_malloc(size_t size, uint attrs = 0,
         PointerMap ptrmap = PointerMap.init)
 {
     if (size == 0)
@@ -2284,7 +2221,7 @@ extern (C) void* gc_malloc(size_t size, uint attrs = 0,
     })();
 }
 
-extern (C) void* gc_calloc(size_t size, uint attrs = 0,
+void* gc_calloc(size_t size, uint attrs = 0,
         PointerMap ptrmap = PointerMap.init)
 {
     if (size == 0)
@@ -2295,7 +2232,7 @@ extern (C) void* gc_calloc(size_t size, uint attrs = 0,
     })();
 }
 
-extern (C) void* gc_realloc(void* p, size_t size, uint attrs = 0,
+void* gc_realloc(void* p, size_t size, uint attrs = 0,
         PointerMap ptrmap = PointerMap.init)
 {
     return locked!(void*, () {
@@ -2304,7 +2241,7 @@ extern (C) void* gc_realloc(void* p, size_t size, uint attrs = 0,
     })();
 }
 
-extern (C) size_t gc_extend(void* p, size_t min_size, size_t max_size)
+size_t gc_extend(void* p, size_t min_size, size_t max_size)
 {
     return locked!(size_t, () {
         assert (Invariant()); scope (exit) assert (Invariant());
@@ -2312,7 +2249,7 @@ extern (C) size_t gc_extend(void* p, size_t min_size, size_t max_size)
     })();
 }
 
-extern (C) size_t gc_reserve(size_t size)
+size_t gc_reserve(size_t size)
 {
     if (size == 0)
         return 0;
@@ -2322,7 +2259,7 @@ extern (C) size_t gc_reserve(size_t size)
     })();
 }
 
-extern (C) void gc_free( void* p )
+void gc_free(void* p)
 {
     if (p is null)
         return;
@@ -2332,17 +2269,20 @@ extern (C) void gc_free( void* p )
     })();
 }
 
-extern (C) void* gc_addrOf( void* p )
+void* gc_addrOf(void* p)
 {
     if (p is null)
         return null;
     return locked!(void*, () {
         assert (Invariant()); scope (exit) assert (Invariant());
-        return findBase(p);
+        Pool* pool = findPool(p);
+        if (pool is null)
+            return null;
+        return pool.findBase(p);
     })();
 }
 
-extern (C) size_t gc_sizeOf( void* p )
+size_t gc_sizeOf(void* p)
 {
     if (p is null)
         return 0;
@@ -2352,7 +2292,7 @@ extern (C) size_t gc_sizeOf( void* p )
     })();
 }
 
-extern (C) BlkInfo gc_query( void* p )
+BlkInfo gc_query(void* p)
 {
     if (p is null)
         return BlkInfo.init;
@@ -2364,7 +2304,7 @@ extern (C) BlkInfo gc_query( void* p )
 
 // NOTE: This routine is experimental.  The stats or function name may change
 //       before it is made officially available.
-extern (C) GCStats gc_stats()
+GCStats gc_stats()
 {
     return locked!(GCStats, () {
         assert (Invariant()); scope (exit) assert (Invariant());
@@ -2372,7 +2312,7 @@ extern (C) GCStats gc_stats()
     })();
 }
 
-extern (C) void gc_addRoot( void* p )
+void gc_addRoot(void* p)
 {
     if (p is null)
         return;
@@ -2383,7 +2323,7 @@ extern (C) void gc_addRoot( void* p )
     })();
 }
 
-extern (C) void gc_addRange(void* p, size_t size)
+void gc_addRange(void* p, size_t size)
 {
     if (p is null || size == 0)
         return;
@@ -2394,7 +2334,7 @@ extern (C) void gc_addRange(void* p, size_t size)
     })();
 }
 
-extern (C) void gc_removeRoot(void* p)
+void gc_removeRoot(void* p)
 {
     if (p is null)
         return;
@@ -2405,7 +2345,7 @@ extern (C) void gc_removeRoot(void* p)
     })();
 }
 
-extern (C) void gc_removeRange(void* p)
+void gc_removeRange(void* p)
 {
     if (p is null)
         return;
@@ -2416,19 +2356,19 @@ extern (C) void gc_removeRange(void* p)
     })();
 }
 
-extern (C) void* gc_weakpointerCreate( Object r )
+void* gc_weakpointerCreate(Object r)
 {
     // weakpointers do their own locking
     return weakpointerCreate(r);
 }
 
-extern (C) void gc_weakpointerDestroy( void* wp )
+void gc_weakpointerDestroy(void* wp)
 {
     // weakpointers do their own locking
     weakpointerDestroy(wp);
 }
 
-extern (C) Object gc_weakpointerGet( void* wp )
+Object gc_weakpointerGet(void* wp)
 {
     // weakpointers do their own locking
     return weakpointerGet(wp);