From 12c1559835a971b49042929b77c41ae6c3f8360b Mon Sep 17 00:00:00 2001 From: Simon Marlow Date: Wed, 16 Apr 2008 22:13:31 +0000 Subject: [PATCH] move the scan block pointer into the gct structure --- rts/sm/GC.c | 23 ++++++++--------------- rts/sm/GC.h | 6 +++--- rts/sm/GCUtils.c | 12 ++++++------ rts/sm/Scav.c | 35 +++++------------------------------ rts/sm/Scav.c-inc | 13 +++++++++++-- 5 files changed, 33 insertions(+), 56 deletions(-) diff --git a/rts/sm/GC.c b/rts/sm/GC.c index cb2f040..68a8981 100644 --- a/rts/sm/GC.c +++ b/rts/sm/GC.c @@ -418,13 +418,13 @@ GarbageCollect ( rtsBool force_major_gc ) // not step 0 for (s = 1; s < total_steps; s++) { ws = &thr->steps[s]; - // Not true? - // ASSERT( ws->scan_bd == ws->todo_bd ); - ASSERT( ws->scan_bd ? ws->scan_bd->u.scan == ws->scan_bd->free : 1 ); // Push the final block - if (ws->scan_bd) { push_scanned_block(ws->scan_bd, ws); } - + if (ws->todo_bd) { + push_scanned_block(ws->todo_bd, ws); + } + + ASSERT(gct->scan_bd == NULL); ASSERT(countBlocks(ws->scavd_list) == ws->n_scavd_blocks); prev = ws->part_list; @@ -1011,8 +1011,6 @@ alloc_gc_thread (int n) ASSERT(s == ws->step->abs_no); ws->gct = t; - ws->scan_bd = NULL; - ws->todo_bd = NULL; ws->buffer_todo_bd = NULL; @@ -1341,8 +1339,6 @@ init_collected_gen (nat g, nat n_threads) ws = &gc_threads[t]->steps[g * RtsFlags.GcFlags.steps + s]; - ws->scan_bd = NULL; - ws->todo_large_objects = NULL; ws->part_list = NULL; @@ -1405,15 +1401,11 @@ init_uncollected_gen (nat g, nat threads) stp->n_blocks -= 1; stp->n_words -= ws->todo_bd->free - ws->todo_bd->start; ws->todo_bd->link = NULL; - - // this block is also the scan block; we must scan - // from the current end point. - ws->scan_bd = ws->todo_bd; - ws->scan_bd->u.scan = ws->scan_bd->free; + // we must scan from the current end point. + ws->todo_bd->u.scan = ws->todo_bd->free; } else { - ws->scan_bd = NULL; ws->todo_bd = NULL; alloc_todo_block(ws,0); } @@ -1442,6 +1434,7 @@ init_gc_thread (gc_thread *t) { t->static_objects = END_OF_STATIC_LIST; t->scavenged_static_objects = END_OF_STATIC_LIST; + t->scan_bd = NULL; t->evac_step = 0; t->failed_to_evac = rtsFalse; t->eager_promotion = rtsTrue; diff --git a/rts/sm/GC.h b/rts/sm/GC.h index 0e0d90a..62a4872 100644 --- a/rts/sm/GC.h +++ b/rts/sm/GC.h @@ -76,9 +76,6 @@ typedef struct step_workspace_ { step * step; // the step for this workspace struct gc_thread_ * gct; // the gc_thread that contains this workspace - // block that is currently being scanned - bdescr * scan_bd; - // where objects to be scavenged go bdescr * todo_bd; StgPtr todo_free; // free ptr for todo_bd @@ -128,6 +125,9 @@ typedef struct gc_thread_ { lnat gc_count; // number of GCs this thread has done + // block that is currently being scanned + bdescr * scan_bd; + // -------------------- // evacuate flags diff --git a/rts/sm/GCUtils.c b/rts/sm/GCUtils.c index 118d5d7..f7b1819 100644 --- a/rts/sm/GCUtils.c +++ b/rts/sm/GCUtils.c @@ -115,16 +115,13 @@ todo_block_full (nat size, step_workspace *ws) ASSERT(bd->link == NULL); ASSERT(bd->step == ws->step); - gct->copied += ws->todo_free - bd->free; - bd->free = ws->todo_free; - // If the global list is not empty, or there's not much work in // this block to push, and there's enough room in // this block to evacuate the current object, then just increase // the limit. if (ws->step->todos != NULL || - (bd->free - bd->u.scan < WORK_UNIT_WORDS / 2)) { - if (bd->free + size < bd->start + BLOCK_SIZE_W) { + (ws->todo_free - bd->u.scan < WORK_UNIT_WORDS / 2)) { + if (ws->todo_free + size < bd->start + BLOCK_SIZE_W) { ws->todo_lim = stg_min(bd->start + 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); @@ -132,11 +129,14 @@ todo_block_full (nat size, step_workspace *ws) } } + 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 != ws->scan_bd) + 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 diff --git a/rts/sm/Scav.c b/rts/sm/Scav.c index 0eb4b11..1295a1d 100644 --- a/rts/sm/Scav.c +++ b/rts/sm/Scav.c @@ -1432,44 +1432,20 @@ loop: } ws = &gct->steps[s]; - if (ws->todo_bd != NULL) - { - bd = ws->todo_bd; - gct->copied += ws->todo_free - bd->free; - bd->free = ws->todo_free; - } + gct->scan_bd = NULL; - // If we have a todo block and no scan block, start - // scanning the todo block. - if (ws->scan_bd == NULL && ws->todo_bd != NULL) - { - ws->scan_bd = ws->todo_bd; - } - // If we have a scan block with some work to do, // scavenge everything up to the free pointer. - if (ws->scan_bd != NULL && ws->scan_bd->u.scan < ws->scan_bd->free) + if (ws->todo_bd->u.scan < ws->todo_free) { if (n_gc_threads == 1) { - scavenge_block1(ws->scan_bd); + scavenge_block1(ws->todo_bd); } else { - scavenge_block(ws->scan_bd); + scavenge_block(ws->todo_bd); } did_something = rtsTrue; + break; } - - if (ws->scan_bd != NULL && ws->scan_bd != ws->todo_bd) - { - ASSERT(ws->scan_bd->u.scan == ws->scan_bd->free); - // we're not going to evac any more objects into - // this block, so push it now. - push_scanned_block(ws->scan_bd, ws); - ws->scan_bd = NULL; - // we might be able to scan the todo block now. - did_something = rtsTrue; - } - - if (did_something) break; // If we have any large objects to scavenge, do them now. if (ws->todo_large_objects) { @@ -1488,7 +1464,6 @@ loop: } else { scavenge_block(bd); } - push_scanned_block(bd, ws); did_something = rtsTrue; break; } diff --git a/rts/sm/Scav.c-inc b/rts/sm/Scav.c-inc index 64677c0..8d5a56c 100644 --- a/rts/sm/Scav.c-inc +++ b/rts/sm/Scav.c-inc @@ -47,11 +47,10 @@ scavenge_block (bdescr *bd) rtsBool saved_eager_promotion; step_workspace *ws; - p = bd->u.scan; - debugTrace(DEBUG_gc, "scavenging block %p (gen %d, step %d) @ %p", bd->start, bd->gen_no, bd->step->no, p); + gct->scan_bd = bd; gct->evac_step = bd->step; saved_evac_step = gct->evac_step; saved_eager_promotion = gct->eager_promotion; @@ -59,6 +58,8 @@ scavenge_block (bdescr *bd) ws = &gct->steps[bd->step->abs_no]; + p = bd->u.scan; + // we might be evacuating into the very object that we're // scavenging, so we have to check the real bd->free pointer each // time around the loop. @@ -454,6 +455,14 @@ scavenge_block (bdescr *bd) // update stats: this is a block that has been scavenged gct->scanned += bd->free - bd->u.scan; bd->u.scan = bd->free; + + if (bd != ws->todo_bd) { + // we're not going to evac any more objects into + // this block, so push it now. + push_scanned_block(bd, ws); + } + + gct->scan_bd = NULL; } #undef scavenge_block -- 1.7.10.4