summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSimon Marlow <marlowsd@gmail.com>2013-05-21 09:30:42 +0100
committerSimon Marlow <marlowsd@gmail.com>2013-05-21 13:38:07 +0100
commit1d3fa868d139fb9a8a5e8b0e408c4c70389db8c3 (patch)
treecc4dce839f49af7d08d8c0a903bd3a65dc42599d
parent22574cf00438922badee0e8e0ea5ef1614c5d17d (diff)
downloadhaskell-1d3fa868d139fb9a8a5e8b0e408c4c70389db8c3.tar.gz
Fix a problem caused by very large objects (#7919)
As far as I can tell the bug should be harmless, apart from the failing assertion. Since the ticket reported crashes, there might be problems elsewhere that aren't triggered by this test case.
-rw-r--r--rts/sm/GCUtils.c17
1 files changed, 12 insertions, 5 deletions
diff --git a/rts/sm/GCUtils.c b/rts/sm/GCUtils.c
index 996b5f6280..21487212e3 100644
--- a/rts/sm/GCUtils.c
+++ b/rts/sm/GCUtils.c
@@ -180,7 +180,7 @@ todo_block_full (nat size, gen_workspace *ws)
// the limit.
if (!looksEmptyWSDeque(ws->todo_q) ||
(ws->todo_free - bd->u.scan < WORK_UNIT_WORDS / 2)) {
- if (ws->todo_free + size < bd->start + bd->blocks * BLOCK_SIZE_W) {
+ if (ws->todo_free + size <= bd->start + bd->blocks * BLOCK_SIZE_W) {
ws->todo_lim = stg_min(bd->start + bd->blocks * BLOCK_SIZE_W,
ws->todo_lim + stg_max(WORK_UNIT_WORDS,size));
debugTrace(DEBUG_gc, "increasing limit for %p to %p", bd->start, ws->todo_lim);
@@ -201,12 +201,19 @@ todo_block_full (nat size, gen_workspace *ws)
{
// If this block does not have enough space to allocate the
// current object, but it also doesn't have any work to push, then
- // push it on to the scanned list. It cannot be empty, because
- // then there would be enough room to copy the current object.
+ // push it on to the scanned list.
if (bd->u.scan == bd->free)
{
- ASSERT(bd->free != bd->start);
- push_scanned_block(bd, ws);
+ if (bd->free == bd->start) {
+ // Normally the block would not be empty, because then
+ // there would be enough room to copy the current
+ // object. However, if the object we're copying is
+ // larger than a block, then we might have an empty
+ // block here.
+ freeGroup(bd);
+ } else {
+ push_scanned_block(bd, ws);
+ }
}
// Otherwise, push this block out to the global list.
else