summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Horton <andrew.j.horton@gmail.com>2013-12-15 15:55:04 +0000
committerIvan Maidanski <ivmai@mail.ru>2014-05-03 00:03:55 +0400
commit5f8f10438297f59b9d747665d6b9b17e377dbe3d (patch)
treee8974622ff5cf8ecff810a136415489919fd0e8a
parent02b2997d8d74ba18359a37e79d103c0d246056e7 (diff)
downloadbdwgc-5f8f10438297f59b9d747665d6b9b17e377dbe3d.tar.gz
Bump GC_collect_at_heapsize in GC_add_to_heap. In the normal case it is
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.
-rw-r--r--alloc.c10
1 files changed, 10 insertions, 0 deletions
diff --git a/alloc.c b/alloc.c
index d3c8b65f..2de0610f 100644
--- 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));