Fri Aug 13 12:51:01 BRT 2010 Marco TĂșlio Gontijo e Silva * Line before inscresing block size. diff -rN -u old-ghc-organizado2/rts/sm/GCUtils.c new-ghc-organizado2/rts/sm/GCUtils.c --- old-ghc-organizado2/rts/sm/GCUtils.c 2010-08-20 10:41:26.000000000 -0300 +++ new-ghc-organizado2/rts/sm/GCUtils.c 2010-08-20 10:41:27.000000000 -0300 @@ -160,6 +160,48 @@ } } +void +todo_block_free (gen_workspace *ws) +{ + bdescr *bd; + bd = ws->todo_bd; + + gct->copied += ws->todo_free - bd->free; + bd->free = ws->todo_free; + + ASSERT(bd->u.scan >= bd->start && bd->u.scan <= bd->free); + + // 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 + { + debugTrace(DEBUG_gc, + "push todo block %p (%ld words), step %d, todo_q: %ld", + bd->start, + (unsigned long)(bd->free - bd->u.scan), + ws->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++; + } + } + } +} + StgPtr todo_block_full (nat size, gen_workspace *ws) { @@ -174,6 +216,29 @@ bd = ws->todo_bd; gen = ws->gen; + // Currently the mark stack is used to ensure that the allocated object + // gets scavenged, so allocation in lines only happens when the mark stack + // is active, that is, in major GCs. + // Check if there is another free line group, and if the object + // fits in it. + if (major_gc && gen->first_line != NULL && + size <= BITS_IN(W_) * gen->first_line->size) { + + if (bd != NULL) { + todo_block_free(ws); + } + + ws->todo_free = (StgPtr) gen->first_line; + ws->todo_lim = ws->todo_free + BITS_IN(W_) * + gen->first_line->size; + gen->first_line = gen->first_line->next; + + ws->todo_bd = NULL; + goto end; + } + // If there isn't another free line group, or the object doesn't fit in + // the next one, allocate in blocks. + // bd == NULL means we're allocating on a line if (bd != NULL) { @@ -195,64 +260,16 @@ return p; } } - - gct->copied += ws->todo_free - bd->free; - bd->free = ws->todo_free; - - ASSERT(bd->u.scan >= bd->start && bd->u.scan <= bd->free); - - // 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 - { - 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++; - } - } - } + todo_block_free(ws); } + // Allocate in blocks ws->todo_bd = NULL; + ws->todo_free = NULL; + ws->todo_lim = NULL; + alloc_todo_block(ws, size); - // Currently the mark stack is used to ensure that the allocated object - // gets scavenged, so allocation in lines only happens when the mark stack - // is active, that is, in major GCs. - if (major_gc && gen->first_line != NULL && - - // Check if there is another free line group, and if the object - // fits in it. - size <= BITS_IN(W_) * gen->first_line->size) { - - ws->todo_free = (StgPtr) gen->first_line; - ws->todo_lim = ws->todo_free + BITS_IN(W_) * - gen->first_line->size; - gen->first_line = gen->first_line->next; - } else { - - // Allocate in blocks - ws->todo_free = NULL; - ws->todo_lim = NULL; - alloc_todo_block(ws, size); - } - +end: p = ws->todo_free; ws->todo_free += size; return p;