move the scan block pointer into the gct structure
authorSimon Marlow <simonmarhaskell@gmail.com>
Wed, 16 Apr 2008 22:13:31 +0000 (22:13 +0000)
committerSimon Marlow <simonmarhaskell@gmail.com>
Wed, 16 Apr 2008 22:13:31 +0000 (22:13 +0000)
rts/sm/GC.c
rts/sm/GC.h
rts/sm/GCUtils.c
rts/sm/Scav.c
rts/sm/Scav.c-inc

index cb2f040..68a8981 100644 (file)
@@ -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;
index 0e0d90a..62a4872 100644 (file)
@@ -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
 
index 118d5d7..f7b1819 100644 (file)
@@ -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 
index 0eb4b11..1295a1d 100644 (file)
@@ -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;
         }
index 64677c0..8d5a56c 100644 (file)
@@ -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