]> granicus.if.org Git - gc/commitdiff
Bump GC_collect_at_heapsize in GC_add_to_heap. In the normal case it is
authorAndrew Horton <andrew.j.horton@gmail.com>
Sun, 15 Dec 2013 15:55:04 +0000 (15:55 +0000)
committerAndrew Horton <andrew.j.horton@gmail.com>
Sun, 15 Dec 2013 15:55:04 +0000 (15:55 +0000)
recalculated straight after. But in the case where it's called directly
from alloc_mark_stack, it isn't. If the mark stack gets very large,
this can cause GC_should_collect to always return true, and
GC_alloc_large to get stuck in a loop calling GC_collect_or_expand.

alloc.c

diff --git a/alloc.c b/alloc.c
index b9039e095e3f8521433c4d881ae6e564e67bac4e..8ca6bb28c5c2a3db2b387b1867c0a91aeb31e5a5 100644 (file)
--- a/alloc.c
+++ b/alloc.c
@@ -1078,6 +1078,16 @@ GC_INNER void GC_add_to_heap(struct hblk *p, size_t bytes)
     phdr -> hb_flags = 0;
     GC_freehblk(p);
     GC_heapsize += bytes;
+
+    /* Normally the caller calculates a new GC_collect_at_heapsize,
+     * but this is also called directly from alloc_mark_stack, so
+     * adjust here. It will be recalculated when called from
+     * GC_expand_hp_inner.
+     */
+    GC_collect_at_heapsize += bytes;
+    if (GC_collect_at_heapsize < GC_heapsize /* wrapped */)
+       GC_collect_at_heapsize = (word)(-1);
+
     if ((word)p <= (word)GC_least_plausible_heap_addr
         || GC_least_plausible_heap_addr == 0) {
         GC_least_plausible_heap_addr = (void *)((ptr_t)p - sizeof(word));