]> git.llucax.com Git - software/dgc/cdgc.git/commitdiff
Make heap precise scanning optional
authorLeandro Lucarella <llucax@gmail.com>
Wed, 28 Jul 2010 20:41:36 +0000 (17:41 -0300)
committerLeandro Lucarella <llucax@gmail.com>
Wed, 28 Jul 2010 20:41:36 +0000 (17:41 -0300)
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.

rt/gc/cdgc/gc.d
rt/gc/cdgc/opts.d

index f5e088c54cd04351d0de17f8b0c26d9f0bab453f..1cec21d4677e297d2e04f6365e311f41a654bbcb 100644 (file)
@@ -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);
+                            }
                         }
                     }
                 }
index f6012b3c047e7195411490fb17d5fc2059d4e156..bb6529a6cf7e4fa5a48ae7bad72b54a91d999e8d 100644 (file)
@@ -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);
     }
 }