]> 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, 18 Dec 2017 07:21:38 +0000 (10:21 +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 ce012aed3685ae5dfdeb2f6b0dc79976c5b58fc2..4a1893720185cd60124f5319ecce041280aa5d18 100644 (file)
--- a/mark.c
+++ b/mark.c
@@ -1908,7 +1908,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 */