From: Leandro Lucarella Date: Wed, 28 Jul 2010 20:41:36 +0000 (-0300) Subject: Make heap precise scanning optional X-Git-Url: https://git.llucax.com/software/dgc/cdgc.git/commitdiff_plain/6a3232d8f1c52377e792b4f4e18fd75f2a3b0f60 Make heap precise scanning optional Now D_GC_OPTS accepts a new boolean option: conservative. When true, the heap is scanned conservatively, even when type information is available. The option defaults to false. --- diff --git a/rt/gc/cdgc/gc.d b/rt/gc/cdgc/gc.d index f5e088c..1cec21d 100644 --- a/rt/gc/cdgc/gc.d +++ b/rt/gc/cdgc/gc.d @@ -92,6 +92,11 @@ package enum BlkAttr : uint ALL_BITS = 0b1111_1111 } +package bool has_pointermap(uint attrs) +{ + return !opts.options.conservative && !(attrs & BlkAttr.NO_SCAN); +} + private { @@ -344,11 +349,9 @@ class GC if (opts.options.sentinel) size += SENTINEL_EXTRA; - bool has_pm = !(attrs & BlkAttr.NO_SCAN); - size_t pm_bitmask_size; + bool has_pm = has_pointermap(attrs); if (has_pm) - pm_bitmask_size = (size_t*).sizeof; - size += pm_bitmask_size; + size += size_t.sizeof; // Compute size bin // Cache previous binsize lookup - Dave Fladebo. @@ -400,7 +403,7 @@ class GC // Return next item from free list gcx.bucket[bin] = (cast(List*)p).next; - if( !(attrs & BlkAttr.NO_SCAN) ) + if (!(attrs & BlkAttr.NO_SCAN)) memset(p + size, 0, capacity - size); if (opts.options.mem_stomp) memset(p, 0xF0, size); @@ -418,9 +421,9 @@ class GC // Store the bit mask AFTER SENTINEL_POST // TODO: store it BEFORE, so the bitmask is protected too if (has_pm) { - auto end_of_blk = cast(size_t**)(p + capacity - pm_bitmask_size); + auto end_of_blk = cast(size_t**)(p + capacity - size_t.sizeof); *end_of_blk = pm_bitmask; - size -= pm_bitmask_size; + size -= size_t.sizeof; } if (opts.options.sentinel) { @@ -525,14 +528,14 @@ class GC void* blk_base_addr = gcx.findBase(p); size_t blk_size = gcx.findSize(p); - bool has_pm = !(attrs & BlkAttr.NO_SCAN); + bool has_pm = has_pointermap(attrs); size_t pm_bitmask_size = 0; if (has_pm) { - pm_bitmask_size = (size_t*).sizeof; + pm_bitmask_size = size_t.sizeof; // Retrieve pointer map bit mask if appropriate if (pm_bitmask is null) { auto end_of_blk = cast(size_t**)(blk_base_addr + - blk_size - pm_bitmask_size); + blk_size - size_t.sizeof); pm_bitmask = *end_of_blk; } } @@ -677,23 +680,23 @@ class GC void* blk_base_addr = gcx.findBase(p); size_t blk_size = gcx.findSize(p); - bool has_pm = !(attrs & BlkAttr.NO_SCAN); + bool has_pm = has_pointermap(attrs); size_t* pm_bitmask = null; size_t pm_bitmask_size = 0; if (has_pm) { - pm_bitmask_size = (size_t*).sizeof; + pm_bitmask_size = size_t.sizeof; // Retrieve pointer map bit mask auto end_of_blk = cast(size_t**)(blk_base_addr + - blk_size - pm_bitmask_size); + blk_size - size_t.sizeof); pm_bitmask = *end_of_blk; + + minsize += size_t.sizeof; + maxsize += size_t.sizeof; } if (blk_size < PAGESIZE) return 0; // cannot extend buckets - minsize += pm_bitmask_size; - maxsize += pm_bitmask_size; - auto psz = blk_size / PAGESIZE; auto minsz = (minsize + PAGESIZE - 1) / PAGESIZE; auto maxsz = (maxsize + PAGESIZE - 1) / PAGESIZE; @@ -726,7 +729,7 @@ class GC gcx.size_cache = 0; if (has_pm) { - new_size -= pm_bitmask_size; + new_size -= size_t.sizeof; auto end_of_blk = cast(size_t**)(blk_base_addr + new_size); *end_of_blk = pm_bitmask; } @@ -914,10 +917,9 @@ class GC uint attrs = gcx.getAttr(pool, biti); size_t size = gcx.findSize(p); - bool has_pm = !(attrs & BlkAttr.NO_SCAN); size_t pm_bitmask_size = 0; - if (has_pm) - pm_bitmask_size = (size_t*).sizeof; + if (has_pointermap(attrs)) + pm_bitmask_size = size_t.sizeof; if (opts.options.sentinel) { // Check for interior pointer @@ -1972,10 +1974,6 @@ struct Gcx size_t pcache = 0; uint changes = 0; - // TODO: add option to be conservative - // force conservative scanning - //pm_bitmask = PointerMap.init.bits.ptr; - size_t type_size = pm_bitmask[0]; size_t* pm_bits = pm_bitmask + 1; @@ -2237,10 +2235,14 @@ struct Gcx pn = cast(size_t)(o - pool.baseAddr) / PAGESIZE; bin = cast(Bins)pool.pagetable[pn]; if (bin < B_PAGE) { - auto end_of_blk = cast(size_t**)(o + binsize[bin] - - (size_t*).sizeof); - size_t* pm_bitmask = *end_of_blk; - mark(o, end_of_blk, pm_bitmask); + if (opts.options.conservative) + mark_conservative(o, o + binsize[bin]); + else { + auto end_of_blk = cast(size_t**)(o + + binsize[bin] - size_t.sizeof); + size_t* pm_bitmask = *end_of_blk; + mark(o, end_of_blk, pm_bitmask); + } } else if (bin == B_PAGE || bin == B_PAGEPLUS) { @@ -2255,10 +2257,14 @@ struct Gcx u++; size_t blk_size = u * PAGESIZE; - auto end_of_blk = cast(size_t**)(o + blk_size - - (size_t*).sizeof); - size_t* pm_bitmask = *end_of_blk; - mark(o, end_of_blk, pm_bitmask); + if (opts.options.conservative) + mark_conservative(o, o + blk_size); + else { + auto end_of_blk = cast(size_t**)(o + blk_size - + size_t.sizeof); + size_t* pm_bitmask = *end_of_blk; + mark(o, end_of_blk, pm_bitmask); + } } } } diff --git a/rt/gc/cdgc/opts.d b/rt/gc/cdgc/opts.d index f6012b3..bb6529a 100644 --- a/rt/gc/cdgc/opts.d +++ b/rt/gc/cdgc/opts.d @@ -51,6 +51,7 @@ struct Options char[MAX_OPT_LEN] collect_stats_file = ""; bool sentinel = false; bool mem_stomp = false; + bool conservative = false; } package Options options; @@ -84,6 +85,8 @@ void process_option(char* opt_name, char* opt_value) options.sentinel = parse_bool(opt_value); else if (cstr_eq(opt_name, "mem_stomp")) options.mem_stomp = parse_bool(opt_value); + else if (cstr_eq(opt_name, "conservative")) + options.conservative = parse_bool(opt_value); } @@ -141,6 +144,7 @@ unittest assert (log_file[0] == '\0'); assert (sentinel == false); assert (mem_stomp == false); + assert (conservative == false); } parse("mem_stomp"); with (options) { @@ -148,13 +152,15 @@ unittest assert (log_file[0] == '\0'); assert (sentinel == false); assert (mem_stomp == true); + assert (conservative == false); } - parse("mem_stomp=0:verbose=2"); + parse("mem_stomp=0:verbose=2:conservative"); with (options) { assert (verbose == 2); assert (log_file[0] == '\0'); assert (sentinel == false); assert (mem_stomp == false); + assert (conservative == true); } parse("log_file=12345 67890:verbose=1:sentinel=4:mem_stomp=1"); with (options) { @@ -162,6 +168,7 @@ unittest assert (cstring.strcmp(log_file.ptr, "12345 67890".ptr) == 0); assert (sentinel == true); assert (mem_stomp == true); + assert (conservative == true); } parse(null); with (options) { @@ -169,6 +176,7 @@ unittest assert (cstring.strcmp(log_file.ptr, "12345 67890".ptr) == 0); assert (sentinel == true); assert (mem_stomp == true); + assert (conservative == true); } }