]> 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>
Fri, 15 Dec 2017 18:09:06 +0000 (21:09 +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 c5450434d049b4c9daba175e8271ed668a58d922..6556b998b0ce64afef9591a9b17708c5f78f41e2 100644 (file)
--- a/mark.c
+++ b/mark.c
@@ -1981,7 +1981,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 */