/************** Debugging ***************************/
//debug = COLLECT_PRINTF; // turn on printf's
-//debug = LOGGING; // log allocations / frees
//debug = MEMSTOMP; // stomp on memory
//debug = SENTINEL; // add underrun/overrrun protection
//debug = PTRCHECK; // more pointer checking
alias GC gc_t;
-/* ======================= Leak Detector =========================== */
-
-
-debug (LOGGING)
-{
- struct Log
- {
- void* p;
- size_t size;
- size_t line;
- char* file;
- void* parent;
-
- void print()
- {
- printf(" p = %x, size = %d, parent = %x ", p, size, parent);
- if (file)
- {
- printf("%s(%u)", file, line);
- }
- printf("\n");
- }
- }
-
-
- struct LogArray
- {
- size_t dim;
- size_t allocdim;
- Log *data;
-
- void Dtor()
- {
- if (data)
- cstdlib.free(data);
- data = null;
- }
-
- void reserve(size_t nentries)
- {
- assert(dim <= allocdim);
- if (allocdim - dim < nentries)
- {
- allocdim = (dim + nentries) * 2;
- assert(dim + nentries <= allocdim);
- if (!data)
- {
- data = cast(Log*) cstdlib.malloc(allocdim * Log.sizeof);
- if (!data && allocdim)
- onOutOfMemoryError();
- }
- else
- {
- Log *newdata = cast(Log*) cstdlib.malloc(
- allocdim * Log.sizeof);
- if (!newdata && allocdim)
- onOutOfMemoryError();
- cstring.memcpy(newdata, data, dim * Log.sizeof);
- cstdlib.free(data);
- data = newdata;
- }
- }
- }
-
-
- void push(Log log)
- {
- reserve(1);
- data[dim++] = log;
- }
-
- void remove(size_t i)
- {
- cstring.memmove(data + i, data + i + 1, (dim - i) * Log.sizeof);
- dim--;
- }
-
-
- size_t find(void *p)
- {
- for (size_t i = 0; i < dim; i++)
- {
- if (data[i].p == p)
- return i;
- }
- return OPFAIL; // not found
- }
-
-
- void copy(LogArray *from)
- {
- reserve(from.dim - dim);
- assert(from.dim <= allocdim);
- cstring.memcpy(data, from.data, from.dim * Log.sizeof);
- dim = from.dim;
- }
- }
-}
-
-
/* ============================ GC =============================== */
size -= SENTINEL_EXTRA;
p = sentinel_add(p);
sentinel_init(p, size);
- gcx.log_malloc(p, size);
if (bits)
{
list.next = gcx.bucket[bin];
gcx.bucket[bin] = list;
}
- gcx.log_free(sentinel_add(p));
}
getStats(stats);
}
- gcx.log_collect();
}
int dummy;
(cast(byte*)this)[0 .. Gcx.sizeof] = 0;
stackBottom = cast(char*)&dummy;
- log_init();
//printf("gcx = %p, self = %x\n", this, self);
inited = 1;
}
pool.Dtor();
cstdlib.free(pool);
}
+
+ // Even when free() can be called with a null pointer, the extra call
+ // might be significant. On hard GC benchmarks making the test for null
+ // here (i.e. not making the call) can reduce the GC time by almost
+ // ~5%.
if (pooltable)
cstdlib.free(pooltable);
-
if (roots)
cstdlib.free(roots);
-
if (ranges)
cstdlib.free(ranges);
}
pool.scan.set(biti);
changes = 1;
}
- log_parent(sentinel_add(pool.baseAddr + biti * 16), sentinel_add(pbot));
}
}
}
gcx.clrBits(pool, biti, BlkAttr.ALL_BITS);
List *list = cast(List *)p;
- log_free(sentinel_add(list));
debug (MEMSTOMP) cstring.memset(p, 0xF3, size);
}
clrBits(pool, biti, BlkAttr.ALL_BITS);
List *list = cast(List *)p;
- log_free(sentinel_add(list));
debug (MEMSTOMP) cstring.memset(p, 0xF3, size);
clrBits(pool, biti, BlkAttr.ALL_BITS);
debug(COLLECT_PRINTF) printf("\tcollecting big %x\n", p);
- log_free(sentinel_add(p));
pool.pagetable[pn] = B_FREE;
freedpages++;
debug (MEMSTOMP) cstring.memset(p, 0xF3, PAGESIZE);
// pool.nomove.clear(biti);
}
-
- /***** Leak Detector ******/
-
-
- debug (LOGGING)
- {
- LogArray current;
- LogArray prev;
-
-
- void log_init()
- {
- current.reserve(1000);
- prev.reserve(1000);
- }
-
-
- void log_malloc(void *p, size_t size)
- {
- Log log;
-
- log.p = p;
- log.size = size;
- log.line = GC.line;
- log.file = GC.file;
- log.parent = null;
-
- GC.line = 0;
- GC.file = null;
-
- current.push(log);
- }
-
-
- void log_free(void *p)
- {
- size_t i;
-
- i = current.find(p);
- if (i != OPFAIL)
- current.remove(i);
- }
-
-
- void log_collect()
- {
- // Print everything in current that is not in prev
- size_t used = 0;
- for (size_t i = 0; i < current.dim; i++)
- {
- size_t j;
-
- j = prev.find(current.data[i].p);
- if (j == OPFAIL)
- current.data[i].print();
- else
- used++;
- }
-
- for (size_t i = 0; i < current.dim; i++)
- {
- void *p;
- size_t j;
-
- p = current.data[i].p;
- if (!findPool(current.data[i].parent))
- {
- j = prev.find(current.data[i].p);
- current.data[i].print();
- }
- }
-
- prev.copy(¤t);
- }
-
-
- void log_parent(void *p, void *parent)
- {
- size_t i;
-
- i = current.find(p);
- if (i == OPFAIL)
- {
- Pool *pool;
- pool = findPool(p);
- assert(pool);
- size_t offset = cast(size_t)(p - pool.baseAddr);
- size_t biti;
- size_t pn = offset / PAGESIZE;
- Bins bin = cast(Bins)pool.pagetable[pn];
- biti = (offset & notbinsize[bin]);
- }
- else
- current.data[i].parent = parent;
- }
-
- }
- else
- {
- void log_init() { }
- void log_malloc(void *p, size_t size) { }
- void log_free(void *p) { }
- void log_collect() { }
- void log_parent(void *p, void *parent) { }
- }
}
baseAddr = null;
topAddr = null;
}
+ // See Gcx.Dtor() for the rationale of the null check.
if (pagetable)
cstdlib.free(pagetable);