+ // If this block is not the scan block, we want to push it out and
+ // make room for a new todo block.
+ if (bd != gct->scan_bd)
+ {
+ // 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.
+ if (bd->u.scan == bd->free)
+ {
+ ASSERT(bd->free != bd->start);
+ push_scanned_block(bd, ws);
+ }
+ // Otherwise, push this block out to the global list.
+ else
+ {
+ generation *gen;
+ gen = ws->gen;
+ debugTrace(DEBUG_gc, "push todo block %p (%ld words), step %d, todo_q: %ld",
+ bd->start, (unsigned long)(bd->free - bd->u.scan),
+ gen->no, dequeElements(ws->todo_q));
+
+ if (!pushWSDeque(ws->todo_q, bd)) {
+ bd->link = ws->todo_overflow;
+ ws->todo_overflow = bd;
+ ws->n_todo_overflow++;
+ }
+ }
+ }
+
+ ws->todo_bd = NULL;
+ ws->todo_free = NULL;
+ ws->todo_lim = NULL;
+
+ alloc_todo_block(ws, size);
+
+ p = ws->todo_free;
+ ws->todo_free += size;
+ return p;
+}
+
+StgPtr
+alloc_todo_block (gen_workspace *ws, nat size)
+{
+ bdescr *bd/*, *hd, *tl */;
+
+ // Grab a part block if we have one, and it has enough room
+ bd = ws->part_list;
+ if (bd != NULL &&
+ bd->start + bd->blocks * BLOCK_SIZE_W - bd->free > (int)size)
+ {
+ ws->part_list = bd->link;
+ ws->n_part_blocks -= bd->blocks;
+ }
+ else
+ {
+ // blocks in to-space get the BF_EVACUATED flag.
+
+// allocBlocks_sync(16, &hd, &tl,
+// ws->step->gen_no, ws->step, BF_EVACUATED);
+//
+// tl->link = ws->part_list;
+// ws->part_list = hd->link;
+// ws->n_part_blocks += 15;
+//
+// bd = hd;
+
+ if (size > BLOCK_SIZE_W) {
+ bd = allocGroup_sync((lnat)BLOCK_ROUND_UP(size*sizeof(W_))
+ / BLOCK_SIZE);
+ } else {
+ bd = allocBlock_sync();
+ }
+ initBdescr(bd, ws->gen, ws->gen->to);
+ bd->flags = BF_EVACUATED;
+ bd->u.scan = bd->free = bd->start;
+ }
+
+ bd->link = NULL;
+
+ ws->todo_bd = bd;
+ ws->todo_free = bd->free;
+ ws->todo_lim = stg_min(bd->start + bd->blocks * BLOCK_SIZE_W,
+ bd->free + stg_max(WORK_UNIT_WORDS,size));
+
+ debugTrace(DEBUG_gc, "alloc new todo block %p for gen %d",
+ bd->free, ws->gen->no);
+
+ return ws->todo_free;