summaryrefslogtreecommitdiff
path: root/rts/sm/GCUtils.c
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 /rts/sm/GCUtils.c
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.
Diffstat (limited to 'rts/sm/GCUtils.c')
-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