]> granicus.if.org Git - gc/commitdiff
Fix marking of disclaim-reachable objects in the incremental mode
authorPetter A. Urkedal <paurkedal@gmail.com>
Sun, 3 Dec 2017 11:42:59 +0000 (12:42 +0100)
committerIvan Maidanski <ivmai@mail.ru>
Mon, 4 Dec 2017 06:18:53 +0000 (09:18 +0300)
Issue #192 (bdwgc).

Unconditional marking is done analogously to marking from uncollectible
blocks, since they are meant to secure access to data for disclaim
notifiers after the data is no longer marked.

* mark.c [ENABLE_DISCLAIM] (GC_push_next_marked_dirty): Honor
MARK_UNCONDITIONALLY when rescanning dirty blocks during incremental
marking.

mark.c

diff --git a/mark.c b/mark.c
index 2c46830926eec70a1fe5608984f45ab724910a63..1da4a1428bbe010550b7c9d6542bae24e33c4a9b 100644 (file)
--- a/mark.c
+++ b/mark.c
@@ -2015,7 +2015,21 @@ STATIC struct hblk * GC_push_next_marked(struct hblk *h)
         h += OBJ_SZ_TO_BLOCKS(hhdr -> hb_sz);
         hhdr = HDR(h);
     }
-    GC_push_marked(h, hhdr);
+#   ifdef ENABLE_DISCLAIM
+      if ((hhdr -> hb_flags & MARK_UNCONDITIONALLY) != 0) {
+        GC_push_unconditionally(h, hhdr);
+
+        /* Then we may ask, why not also add the MARK_UNCONDITIONALLY   */
+        /* case to GC_push_next_marked, which is also applied to        */
+        /* uncollectible blocks?  But it seems to me that the function  */
+        /* does not need to scan uncollectible (and unconditionally     */
+        /* marked) blocks since those are already handled in the        */
+        /* MS_PUSH_UNCOLLECTABLE phase.                                 */
+      } else
+#   endif
+    /* else */ {
+      GC_push_marked(h, hhdr);
+    }
     return(h + OBJ_SZ_TO_BLOCKS(hhdr -> hb_sz));
   }
 #endif /* !GC_DISABLE_INCREMENTAL */