[project @ 1996-01-11 14:06:51 by partain]
[ghc-hetmet.git] / ghc / runtime / storage / SMap.lc
index e82a986..27ec2be 100644 (file)
@@ -30,14 +30,10 @@ P_ heap_space = 0;          /* Address of first word of slab
 
 P_ hp_start;           /* Value of Hp when reduction was resumed */
 
-#if defined(PROMOTION_DATA)     /* For dead promote & premature promote data */
-P_ thisbase;                /* Start of old gen before this minor collection */
-P_ prevbase;                /* Start of old gen before previous minor collection */
-I_ prev_prom = 0;              /* Promoted previous minor collection */
-I_ dead_prev_prom = 0;         /* Dead words promoted previous minor */
-#endif /* PROMOTION_DATA */
-
-#if defined(_GC_DEBUG)
+static I_ allocd_since_last_major_GC = 0;
+       /* words alloced since last major GC; used when forcing GC */
+
+#if defined(DEBUG)
 void
 debug_look_for (start, stop, villain)
   P_ start, stop, villain;
@@ -51,21 +47,21 @@ debug_look_for (start, stop, villain)
 }
 #endif
 
-I_
-initHeap( sm )
-    smInfo *sm;    
+rtsBool
+initHeap(smInfo * sm)
 {
     if (heap_space == 0) { /* allocates if it doesn't already exist */
 
        /* Allocate the roots space */
-       sm->roots = (P_ *) xmalloc( SM_MAXROOTS * sizeof(W_) );
+       sm->roots = (P_ *) stgMallocWords(SM_MAXROOTS, "initHeap (roots)");
 
        /* Allocate the heap */
-       heap_space = (P_) xmalloc((SM_word_heap_size + EXTRA_HEAP_WORDS) * sizeof(W_));
+       heap_space = (P_) stgMallocWords(RTSflags.GcFlags.heapSize + EXTRA_HEAP_WORDS,
+                                        "initHeap (heap)");
 
        /* ToDo (ADR): trash entire heap contents */
 
-       if (SM_force_gc == USE_2s) {
+       if (RTSflags.GcFlags.force2s) {
            stat_init("TWOSPACE(APPEL)",
                      " No of Roots  Caf   Caf    Astk   Bstk",
                      "Astk Bstk Reg  No  bytes  bytes  bytes");
@@ -77,8 +73,8 @@ initHeap( sm )
     }
     sm->hardHpOverflowSize = 0;
 
-    if (SM_force_gc == USE_2s) {
-       I_ semi_space_words = SM_word_heap_size / 2;
+    if (RTSflags.GcFlags.force2s) {
+       I_ semi_space_words = RTSflags.GcFlags.heapSize / 2;
        appelInfo.space[0].base = HEAP_FRAME_BASE(heap_space, semi_space_words);
        appelInfo.space[1].base = HEAP_FRAME_BASE(heap_space + semi_space_words, semi_space_words);
        appelInfo.space[0].lim = HEAP_FRAME_LIMIT(heap_space, semi_space_words);
@@ -88,37 +84,28 @@ initHeap( sm )
 
        sm->hp = hp_start = appelInfo.space[appelInfo.semi_space].base - 1;
 
-       if (SM_alloc_size) {
-           sm->hplim = sm->hp + SM_alloc_size;
-           SM_alloc_min = 0; /* No min; alloc size specified */
+       if (! RTSflags.GcFlags.allocAreaSizeGiven) {
+           sm->hplim = appelInfo.space[appelInfo.semi_space].lim;
+       } else {
+           sm->hplim = sm->hp + RTSflags.GcFlags.allocAreaSize;
+
+           RTSflags.GcFlags.minAllocAreaSize = 0; /* specified size takes precedence */
 
            if (sm->hplim > appelInfo.space[appelInfo.semi_space].lim) {
                fprintf(stderr, "Not enough heap for requested alloc size\n");
-               return -1;
+               return rtsFalse;
            }
-       } else {
-           sm->hplim = appelInfo.space[appelInfo.semi_space].lim;
        }
 
-#if defined(FORCE_GC)
-        if (force_GC) {
-          if (sm->hplim > sm->hp + GCInterval) {
-              sm->hplim = sm->hp + GCInterval;
-           }
-           else {
+        if (RTSflags.GcFlags.forceGC) {
+          if (sm->hplim > sm->hp + RTSflags.GcFlags.forcingInterval) {
+              sm->hplim = sm->hp + RTSflags.GcFlags.forcingInterval;
+           } else {
               /* no point in forcing GC, 
-                 as the semi-space is smaller than GCInterval */
-              force_GC = 0; 
+                 as the semi-space is smaller than forcingInterval */
+              RTSflags.GcFlags.forceGC = rtsFalse;
            }
         }
-#endif /* FORCE_GC */
-
-#if defined(LIFE_PROFILE)
-        sm->hplim = sm->hp + ((sm->hplim - sm->hp) / 2); /* space for HpLim incr */
-        if (do_life_prof) {
-           sm->hplim = sm->hp + LifeInterval;
-        }
-#endif /* LIFE_PROFILE */
 
        sm->OldLim = appelInfo.oldlim;
        sm->CAFlist = NULL;
@@ -127,55 +114,59 @@ initHeap( sm )
        initExtensions( sm );
 #endif
 
-       if (SM_trace) {
+       if (RTSflags.GcFlags.trace) {
            fprintf(stderr, "APPEL(2s) Heap: 0x%lx .. 0x%lx\n",
-                   (W_) heap_space, (W_) (heap_space - 1 + SM_word_heap_size));
+                   (W_) heap_space, (W_) (heap_space - 1 + RTSflags.GcFlags.heapSize));
            fprintf(stderr, "Initial: space %ld, base 0x%lx, lim 0x%lx\n         hp 0x%lx, hplim 0x%lx, free %lu\n",
                    appelInfo.semi_space,
                    (W_) appelInfo.space[appelInfo.semi_space].base,
                    (W_) appelInfo.space[appelInfo.semi_space].lim,
                    (W_) sm->hp, (W_) sm->hplim, (W_) (sm->hplim - sm->hp) * sizeof(W_));
        }
-       return 0;
+       return rtsTrue;
     }
 
 
 /* So not forced 2s */
 
-    appelInfo.newlim  = heap_space + SM_word_heap_size - 1;
-    if (SM_alloc_size) {
-       appelInfo.newfixed = SM_alloc_size;
-       appelInfo.newmin   = SM_alloc_size;
-        appelInfo.newbase  = heap_space + SM_word_heap_size - appelInfo.newfixed;
+    appelInfo.newlim  = heap_space + RTSflags.GcFlags.heapSize - 1;
+    if (RTSflags.GcFlags.allocAreaSizeGiven) {
+       appelInfo.newfixed = RTSflags.GcFlags.allocAreaSize;
+       appelInfo.newmin   = RTSflags.GcFlags.allocAreaSize;
+        appelInfo.newbase  = heap_space + RTSflags.GcFlags.heapSize - appelInfo.newfixed;
     } else {
        appelInfo.newfixed = 0;
-       appelInfo.newmin   = SM_alloc_min;
-       appelInfo.newbase  = heap_space + (SM_word_heap_size / 2);
+       appelInfo.newmin   = RTSflags.GcFlags.minAllocAreaSize;
+       appelInfo.newbase  = heap_space + (RTSflags.GcFlags.heapSize / 2);
     }
 
     appelInfo.oldbase = heap_space;
     appelInfo.oldlim  = heap_space - 1;
     appelInfo.oldlast = heap_space - 1;
-    appelInfo.oldmax  = heap_space - 1 + SM_word_heap_size - 2*appelInfo.newmin;
+    appelInfo.oldmax  = heap_space - 1 + RTSflags.GcFlags.heapSize - 2*appelInfo.newmin;
 
     if (appelInfo.oldbase > appelInfo.oldmax) {
        fprintf(stderr, "Not enough heap for requested/minimum allocation area\n");
-       return -1;
+       fprintf(stderr, "heap_space=%ld\n", heap_space);
+       fprintf(stderr, "heapSize=%ld\n", RTSflags.GcFlags.heapSize);
+       fprintf(stderr, "newmin=%ld\n", appelInfo.newmin);
+       return rtsFalse;
     }
 
-    appelInfo.bit_words = (SM_word_heap_size + BITS_IN(BitWord) - 1) / BITS_IN(BitWord);
+    appelInfo.bit_words = (RTSflags.GcFlags.heapSize + BITS_IN(BitWord) - 1) / BITS_IN(BitWord);
     appelInfo.bits      = (BitWord *)(appelInfo.newlim) - appelInfo.bit_words;
+
     if (appelInfo.bit_words > appelInfo.newmin)
-        appelInfo.oldmax = heap_space - 1 + SM_word_heap_size - appelInfo.bit_words - appelInfo.newmin;
+        appelInfo.oldmax = heap_space - 1 + RTSflags.GcFlags.heapSize - appelInfo.bit_words - appelInfo.newmin;
 
-    if (SM_major_gen_size) {
-       appelInfo.oldthresh = heap_space -1 + SM_major_gen_size;
+    if (RTSflags.GcFlags.specifiedOldGenSize) {
+       appelInfo.oldthresh = heap_space -1 + RTSflags.GcFlags.specifiedOldGenSize;
        if (appelInfo.oldthresh > appelInfo.oldmax) {
            fprintf(stderr, "Not enough heap for requested major resid size\n");
-           return -1;
+           return rtsFalse;
        }
     } else {
-       appelInfo.oldthresh = heap_space + SM_word_heap_size * 2 / 3; /* Initial threshold -- 2/3rds */
+       appelInfo.oldthresh = heap_space + RTSflags.GcFlags.heapSize * 2 / 3; /* Initial threshold -- 2/3rds */
        if (appelInfo.oldthresh > appelInfo.oldmax)
            appelInfo.oldthresh = appelInfo.oldmax;
     }
@@ -183,11 +174,10 @@ initHeap( sm )
     sm->hp = hp_start = appelInfo.newbase - 1;
     sm->hplim = appelInfo.newlim;
 
-#if defined(FORCE_GC)
-        if (force_GC && (sm->hplim > sm->hp + GCInterval)) {
-              sm->hplim = sm->hp + GCInterval;
-           }
-#endif /* FORCE_GC */
+    if (RTSflags.GcFlags.forceGC
+     && sm->hplim > sm->hp + RTSflags.GcFlags.forcingInterval) {
+       sm->hplim = sm->hp + RTSflags.GcFlags.forcingInterval;
+    }
 
     sm->OldLim = appelInfo.oldlim;
 
@@ -201,14 +191,9 @@ initHeap( sm )
 
     appelInfo.PromMutables = 0;
 
-#if defined(PROMOTION_DATA)   /* For dead promote & premature promote data */
-    prevbase = appelInfo.oldlim + 1;
-    thisbase = appelInfo.oldlim + 1;
-#endif /* PROMOTION_DATA */
-
-    if (SM_trace) {
+    if (RTSflags.GcFlags.trace) {
        fprintf(stderr, "APPEL Heap: 0x%lx .. 0x%lx\n",
-               (W_) heap_space, (W_) (heap_space - 1 + SM_word_heap_size));
+               (W_) heap_space, (W_) (heap_space - 1 + RTSflags.GcFlags.heapSize));
        fprintf(stderr, "Initial: newbase 0x%lx newlim 0x%lx; base 0x%lx lim 0x%lx thresh 0x%lx max 0x%lx\n         hp 0x%lx, hplim 0x%lx\n",
                (W_) appelInfo.newbase, (W_) appelInfo.newlim,
                (W_) appelInfo.oldbase, (W_) appelInfo.oldlim,
@@ -216,17 +201,12 @@ initHeap( sm )
                (W_) sm->hp, (W_) sm->hplim);
     }
 
-    return 0;
+    return rtsTrue; /* OK */
 }
 
 static I_
-collect2s(reqsize, sm)
-    W_ reqsize;
-    smInfo *sm;
+collect2s(W_ reqsize, smInfo *sm)
 {
-#if defined(LIFE_PROFILE)
-    I_ next_interval;  /* if doing profile */
-#endif
     I_ free_space,     /* No of words of free space following GC */
         alloc,                 /* Number of words allocated since last GC */
        resident,       /* Number of words remaining after GC */
@@ -236,15 +216,11 @@ collect2s(reqsize, sm)
 
     SAVE_REGS(&ScavRegDump);        /* Save registers */
 
-#if defined(LIFE_PROFILE)
-    if (do_life_prof) {        life_profile_setup(); }
-#endif /* LIFE_PROFILE */
-
-#if defined(USE_COST_CENTRES)
+#if defined(PROFILING)
     if (interval_expired) { heap_profile_setup(); }
-#endif  /* USE_COST_CENTRES */
+#endif  /* PROFILING */
   
-    if (SM_trace)
+    if (RTSflags.GcFlags.trace)
        fprintf(stderr, "Start: space %ld, base 0x%lx, lim 0x%lx\n       hp 0x%lx, hplim 0x%lx, req %lu\n",
                appelInfo.semi_space,
                (W_) appelInfo.space[appelInfo.semi_space].base,
@@ -291,33 +267,32 @@ collect2s(reqsize, sm)
     resident = sm->hp - (appelInfo.space[appelInfo.semi_space].base - 1);
     DO_MAX_RESIDENCY(resident); /* stats only */
 
-    if (SM_alloc_size) {
-       sm->hplim = sm->hp + SM_alloc_size;
+    if (! RTSflags.GcFlags.allocAreaSizeGiven) {
+       sm->hplim = appelInfo.space[appelInfo.semi_space].lim;
+       free_space = sm->hplim - sm->hp;
+    } else {
+       sm->hplim = sm->hp + RTSflags.GcFlags.allocAreaSize;
        if (sm->hplim > appelInfo.space[appelInfo.semi_space].lim) {
            free_space = 0;
        } else {
-           free_space = SM_alloc_size;
+           free_space = RTSflags.GcFlags.allocAreaSize;
        }
-    } else {
-       sm->hplim = appelInfo.space[appelInfo.semi_space].lim;
-       free_space = sm->hplim - sm->hp;
     }
 
-#if defined(FORCE_GC)
-    if (force_GC && (sm->hplim > sm->hp + GCInterval)) {
-              sm->hplim = sm->hp + GCInterval;
-           }
-#endif /* FORCE_GC */
+    if (RTSflags.GcFlags.forceGC
+     && sm->hplim > sm->hp + RTSflags.GcFlags.forcingInterval) {
+       sm->hplim = sm->hp + RTSflags.GcFlags.forcingInterval;
+    }
 
-    if (SM_stats_verbose) {
+    if (RTSflags.GcFlags.giveStats) {
        char comment_str[BIG_STRING_LEN];
 #ifndef PAR
-       sprintf(comment_str, "%4u %4ld %3ld %3ld %6lu %6lu %6lu  2s",
-               (SUBTRACT_A_STK(MAIN_SpA, stackInfo.botA) + 1),
+       sprintf(comment_str, "%4lu %4ld %3ld %3ld %6lu %6lu %6lu  2s",
+               (W_) (SUBTRACT_A_STK(MAIN_SpA, stackInfo.botA) + 1),
                bstk_roots, sm->rootno,
                caf_roots, extra_caf_words*sizeof(W_),
-               (SUBTRACT_A_STK(MAIN_SpA, stackInfo.botA) + 1)*sizeof(W_),
-               (SUBTRACT_B_STK(MAIN_SpB, stackInfo.botB) + 1)*sizeof(W_));
+               (W_) (SUBTRACT_A_STK(MAIN_SpA, stackInfo.botA) + 1)*sizeof(W_),
+               (W_) (SUBTRACT_B_STK(MAIN_SpB, stackInfo.botB) + 1)*sizeof(W_));
 #else
        /* ToDo: come up with some interesting statistics for the parallel world */
        sprintf(comment_str, "%4u %4ld %3ld %3ld %6lu %6lu %6lu  2s",
@@ -325,40 +300,25 @@ collect2s(reqsize, sm)
 
 #endif
 
-#if defined(LIFE_PROFILE)
-       if (do_life_prof) {
-           strcat(comment_str, " life");
-       }
-#endif
-#if defined(USE_COST_CENTRES)
-       if (interval_expired) {
-           strcat(comment_str, " prof");
-       }
+#if defined(PROFILING)
+       if (interval_expired) { strcat(comment_str, " prof"); }
 #endif
 
-       stat_endGC(alloc, SM_word_heap_size, resident, comment_str);
+       stat_endGC(alloc, RTSflags.GcFlags.heapSize, resident, comment_str);
     } else {
-       stat_endGC(alloc, SM_word_heap_size, resident, "");
+       stat_endGC(alloc, RTSflags.GcFlags.heapSize, resident, "");
     }
 
-#if defined(LIFE_PROFILE)
-      free_space = free_space / 2; /* space for HpLim incr */
-      if (do_life_prof) {
-         next_interval = life_profile_done(alloc, reqsize);
-         free_space -= next_interval;  /* ensure interval available */
-      }
-#endif /* LIFE_PROFILE */
-
-#if defined(USE_COST_CENTRES) || defined(GUM)
+#if defined(PROFILING) || defined(PAR)
       if (interval_expired) {
-# if defined(USE_COST_CENTRES)
+# if defined(PROFILING)
          heap_profile_done();
 # endif
          report_cc_profiling(0 /*partial*/);
       }
-#endif /* USE_COST_CENTRES */
+#endif /* PROFILING */
 
-    if (SM_trace)
+    if (RTSflags.GcFlags.trace)
        fprintf(stderr, "Done:  space %ld, base 0x%lx, lim 0x%lx\n       hp 0x%lx, hplim 0x%lx, free %lu\n",
                appelInfo.semi_space,
                (W_) appelInfo.space[appelInfo.semi_space].base,
@@ -371,6 +331,7 @@ collect2s(reqsize, sm)
            we just came from. */
     {
       I_ old_space = NEXT_SEMI_SPACE(appelInfo.semi_space);
+
       TrashMem(appelInfo.space[old_space].base, appelInfo.space[old_space].lim);
       TrashMem(sm->hp+1, sm->hplim);
     }
@@ -378,21 +339,9 @@ collect2s(reqsize, sm)
 
     RESTORE_REGS(&ScavRegDump);     /* Restore Registers */
 
-    if ( (SM_alloc_min > free_space) || (reqsize > free_space) ) {
+    if (free_space < RTSflags.GcFlags.minAllocAreaSize || free_space < reqsize)
       return( GC_HARD_LIMIT_EXCEEDED );        /* Heap absolutely exhausted */
-    } else {
-
-#if defined(LIFE_PROFILE)
-       /* ToDo: this may not be right now (WDP 94/11) */
-
-       /* space for HpLim incr */
-       sm->hplim = sm->hp + ((sm->hplim - sm->hp) / 2);
-       if (do_life_prof) {
-           /* set hplim for next life profile */
-           sm->hplim = sm->hp + next_interval;
-       }
-#endif /* LIFE_PROFILE */
-
+    else {
        if (reqsize + sm->hardHpOverflowSize > free_space) {
          return( GC_SOFT_LIMIT_EXCEEDED );     /* Heap nearly exhausted */
        } else {
@@ -409,40 +358,29 @@ collectHeap(reqsize, sm, do_full_collection)
     rtsBool do_full_collection; /* do a major collection regardless? */
 {
     I_ bstk_roots, caf_roots, mutable, old_words;
-    P_ oldptr, old_start, mutptr, prevmut;
+    P_ old_start, mutptr, prevmut;
     P_ CAFptr, prevCAF;
-    P_ next;
 
     I_ alloc,          /* Number of words allocated since last GC */
        resident;       /* Number of words remaining after GC */
 
-#if defined(PROMOTION_DATA)   /* For dead promote & premature promote data */
-    I_ promote,        /* Promoted this minor collection */
-        dead_prom,      /* Dead words promoted this minor */
-        dead_prev;      /* Promoted words that died since previos minor collection */
-    I_  root;
-    P_ base[2];
-#endif /* PROMOTION_DATA */
-
     fflush(stdout);     /* Flush stdout at start of GC */
 
-    if (SM_force_gc == USE_2s) {
+    if (RTSflags.GcFlags.force2s) {
        return collect2s(reqsize, sm);
     }
 
     SAVE_REGS(&ScavRegDump); /* Save registers */
 
-    if (SM_trace)
+    if (RTSflags.GcFlags.trace)
        fprintf(stderr, "Start: newbase 0x%lx, newlim 0x%lx\n        hp 0x%lx, hplim 0x%lx, req %lu\n",
                (W_) appelInfo.newbase, (W_) appelInfo.newlim, (W_) sm->hp, (W_) sm->hplim, reqsize * sizeof(W_));
 
     alloc = sm->hp - hp_start;
     stat_startGC(alloc);
 
-#ifdef FORCE_GC
-    alloc_since_last_major_GC += sm->hplim - hp_start;
+    allocd_since_last_major_GC += sm->hplim - hp_start;
     /* this is indeed supposed to be less precise than alloc above */
-#endif /* FORCE_GC */
 
     /* COPYING COLLECTION */
 
@@ -481,6 +419,7 @@ collectHeap(reqsize, sm, do_full_collection)
     while ( mutptr ) {
 
        /* Scavenge the OldMutable */
+       P_ orig_mutptr = mutptr;
        P_ info = (P_) INFO_PTR(mutptr);
        StgScavPtr scav_code = SCAV_CODE(info);
        Scav = mutptr;
@@ -496,6 +435,7 @@ collectHeap(reqsize, sm, do_full_collection)
            prevmut = mutptr;
            mutptr = (P_) MUT_LINK(mutptr);
        }
+
        mutable++;
     }
 
@@ -559,11 +499,11 @@ collectHeap(reqsize, sm, do_full_collection)
     resident = appelInfo.oldlim - sm->OldLim;
     /* DONT_DO_MAX_RESIDENCY -- it is just a minor collection */
 
-    if (SM_stats_verbose) {
+    if (RTSflags.GcFlags.giveStats) {
        char minor_str[BIG_STRING_LEN];
 #ifndef PAR
-       sprintf(minor_str, "%4u %4ld %3ld %3ld  %4ld        Minor",
-             (SUBTRACT_A_STK(MAIN_SpA, stackInfo.botA) + 1),
+       sprintf(minor_str, "%4lu %4ld %3ld %3ld  %4ld        Minor",
+             (W_) (SUBTRACT_A_STK(MAIN_SpA, stackInfo.botA) + 1),
              bstk_roots, sm->rootno, caf_roots, mutable); /* oldnew_roots, old_words */
 #else
        /* ToDo: come up with some interesting statistics for the parallel world */
@@ -577,41 +517,26 @@ collectHeap(reqsize, sm, do_full_collection)
 
     /* Note: if do_full_collection we want to force a full collection. [ADR] */
 
-#ifdef FORCE_GC
-    if (force_GC && (alloc_since_last_major_GC >= GCInterval)) { 
-       do_full_collection = 1; 
+    if (RTSflags.GcFlags.forceGC
+     && allocd_since_last_major_GC >= RTSflags.GcFlags.forcingInterval) { 
+       do_full_collection = 1;
     }
-#endif /* FORCE_GC */
-
-#if defined(PROMOTION_DATA)   /* For dead promote & premature promote data major required */
-
-    if (! SM_stats_verbose &&
-       (appelInfo.oldlim < appelInfo.oldthresh) &&
-       (reqsize + sm->hardHpOverflowSize <= appelInfo.newlim - appelInfo.newbase) &&
-       (! do_full_collection) ) {
-
-#else  /* ! PROMOTION_DATA */
 
     if ((appelInfo.oldlim < appelInfo.oldthresh) &&
        (reqsize + sm->hardHpOverflowSize <= appelInfo.newlim - appelInfo.newbase) &&
        (! do_full_collection) ) {
 
-#endif /* ! PROMOTION_DATA */
-
        sm->hp = hp_start = appelInfo.newbase - 1;
        sm->hplim = appelInfo.newlim;
 
-#if defined(FORCE_GC)
-        if (force_GC && 
-            (alloc_since_last_major_GC + (sm->hplim - hp_start) > GCInterval))
-        {
-              sm->hplim = sm->hp + (GCInterval - alloc_since_last_major_GC);
+        if (RTSflags.GcFlags.forceGC
+        && (allocd_since_last_major_GC + (sm->hplim - hp_start) > RTSflags.GcFlags.forcingInterval)) {
+           sm->hplim = sm->hp + (RTSflags.GcFlags.forcingInterval - allocd_since_last_major_GC);
         }
-#endif /* FORCE_GC */
 
        sm->OldLim = appelInfo.oldlim;
 
-       if (SM_trace) {
+       if (RTSflags.GcFlags.trace) {
            fprintf(stderr, "Minor: newbase 0x%lx newlim 0x%lx; base 0x%lx lim 0x%lx thresh 0x%lx max 0x%lx\n        hp 0x%lx, hplim 0x%lx, free %lu\n",
                    (W_) appelInfo.newbase,   (W_) appelInfo.newlim,
                    (W_) appelInfo.oldbase,   (W_) appelInfo.oldlim,
@@ -632,20 +557,12 @@ collectHeap(reqsize, sm, do_full_collection)
 
     DEBUG_STRING("Major Collection Required");
 
-#ifdef FORCE_GC
-    alloc_since_last_major_GC = 0;
-#endif /* FORCE_GC */
+    allocd_since_last_major_GC = 0;
 
     stat_startGC(0);
 
     alloc = (appelInfo.oldlim - appelInfo.oldbase) + 1;
 
-#if defined(PROMOTION_DATA)   /* For dead promote & premature promote data */
-    if (SM_stats_verbose) {
-       promote = appelInfo.oldlim - thisbase + 1;
-    }
-#endif /* PROMOTION_DATA */
-
     appelInfo.bit_words = (alloc + BITS_IN(BitWord) - 1) / BITS_IN(BitWord);
     appelInfo.bits      = (BitWord *)(appelInfo.newlim) - appelInfo.bit_words;
                          /* For some reason, this doesn't seem to use the last
@@ -691,63 +608,6 @@ collectHeap(reqsize, sm, do_full_collection)
 
     LinkCAFs(appelInfo.OldCAFlist);
 
-#if defined(PROMOTION_DATA)   /* For dead promote & premature promote data */
-    /* What does this have to do with CAFs? -- JSM */
-    if (SM_stats_verbose) {
-       base[0] = thisbase;
-       base[1] = prevbase;
-
-       if (SM_trace) {
-           fprintf(stderr, "Promote Bases: lim 0x%lx this 0x%lx prev 0x%lx Actual: ",
-                   appelInfo.oldlim + 1, thisbase, prevbase);
-       }
-       
-       /* search for first live closure for thisbase & prevbase */
-       for (root = 0; root < 2; root++) {
-           P_ baseptr, search, scan_w_start;
-           I_ prev_words, bit_words, bit_rem;
-           BitWord *bit_array_ptr, *bit_array_end;
-           
-           baseptr = base[root];
-           prev_words = (baseptr - appelInfo.oldbase);
-           bit_words  = prev_words / BITS_IN(BitWord);
-           bit_rem    = prev_words & (BITS_IN(BitWord) - 1);
-           
-           bit_array_ptr = appelInfo.bits + bit_words;
-           bit_array_end = appelInfo.bits + appelInfo.bit_words;
-           scan_w_start  = baseptr - bit_rem;
-           
-           baseptr = 0;
-           while (bit_array_ptr < bit_array_end && !baseptr) {
-               BitWord w = *(bit_array_ptr++);
-               search = scan_w_start;
-               if (bit_rem) {
-                   search += bit_rem;
-                   w >>= bit_rem;
-                   bit_rem = 0;                
-               }
-               while (w && !baseptr) {
-                   if (w & 0x1) {     /* bit set -- found first closure */
-                       baseptr = search;
-                   } else {
-                       search++;      /* look at next bit */
-                       w >>= 1;
-                   }
-               }
-               scan_w_start += BITS_IN(BitWord);
-           }
-           if (SM_trace) {
-               fprintf(stderr, "0x%lx%s", baseptr, root == 2 ? "\n" : " ");
-           }
-           
-           base[root] = baseptr;
-           if (baseptr) {
-               LINK_LOCATION_TO_CLOSURE(base + root);
-           }
-       }
-    }
-#endif /* PROMOTION_DATA */
-
     LinkRoots( sm->roots, sm->rootno );
 #ifdef CONCURRENT
     LinkSparks();
@@ -785,7 +645,7 @@ collectHeap(reqsize, sm, do_full_collection)
 
     /* set major threshold, if not fixed */
     /* next major collection when old gen occupies 2/3rds of the free space or exceeds oldmax */
-    if (! SM_major_gen_size) {
+    if (! RTSflags.GcFlags.specifiedOldGenSize) {
        appelInfo.oldthresh = appelInfo.oldlim + (appelInfo.newlim - appelInfo.oldlim) * 2 / 3;
        if (appelInfo.oldthresh > appelInfo.oldmax)
            appelInfo.oldthresh = appelInfo.oldmax;
@@ -794,70 +654,37 @@ collectHeap(reqsize, sm, do_full_collection)
     sm->hp = hp_start = appelInfo.newbase - 1;
     sm->hplim = appelInfo.newlim;
     
-#if defined(FORCE_GC)
-        if (force_GC && (sm->hplim > sm->hp + GCInterval)) {
-              sm->hplim = sm->hp + GCInterval;
-        }
-#endif /* FORCE_GC */
+    if (RTSflags.GcFlags.forceGC
+     && sm->hplim > sm->hp + RTSflags.GcFlags.forcingInterval) {
+       sm->hplim = sm->hp + RTSflags.GcFlags.forcingInterval;
+    }
 
     sm->OldLim = appelInfo.oldlim;
 
-#if defined(PROMOTION_DATA)   /* For dead promote & premature promote data */
-    if (SM_stats_verbose) {
-       /* restore moved thisbase & prevbase */
-       thisbase = base[0] ? base[0] : appelInfo.oldlim + 1;
-       prevbase = base[1] ? base[1] : appelInfo.oldlim + 1;
-
-       /* here are the numbers we want */
-       dead_prom = promote - (appelInfo.oldlim + 1 - thisbase);
-       dead_prev = prev_prom - (thisbase - prevbase) - dead_prev_prom;
-
-       if (SM_trace) {
-           fprintf(stderr, "Collect Bases: lim 0x%lx this 0x%lx prev 0x%lx\n",
-                   appelInfo.oldlim + 1, thisbase, prevbase);
-           fprintf(stderr, "Promoted: %ld Dead: this %ld prev %ld + %ld\n",
-                   promote, dead_prom, dead_prev_prom, dead_prev);
-       }
-
-       /* save values for next collection */
-       prev_prom = promote;
-       dead_prev_prom = dead_prom;
-       prevbase = thisbase;
-       thisbase = appelInfo.oldlim + 1;
-    }
-#endif /* PROMOTION_DATA */
-
 #ifdef HAVE_VADVISE
     vadvise(VA_NORM);
 #endif
 
-    if (SM_stats_verbose) {
+    if (RTSflags.GcFlags.giveStats) {
        char major_str[BIG_STRING_LEN];
 #ifndef PAR
-       sprintf(major_str, "%4u %4ld %3ld %3ld  %4d %4d  *Major* %4.1f%%",
-               (SUBTRACT_A_STK(MAIN_SpA, stackInfo.botA) + 1),
+       sprintf(major_str, "%4lu %4ld %3ld %3ld  %4d %4d  *Major* %4.1f%%",
+               (W_) (SUBTRACT_A_STK(MAIN_SpA, stackInfo.botA) + 1),
                bstk_roots, sm->rootno, appelInfo.OldCAFno,
-               0, 0, resident / (StgFloat) SM_word_heap_size * 100);
+               0, 0, resident / (StgDouble) RTSflags.GcFlags.heapSize * 100);
 #else
        /* ToDo: come up with some interesting statistics for the parallel world */
        sprintf(major_str, "%4u %4ld %3ld %3ld  %4d %4d  *Major* %4.1f%%",
                0, 0L, sm->rootno, appelInfo.OldCAFno, 0, 0,
-               resident / (StgFloat) SM_word_heap_size * 100);
+               resident / (StgDouble) RTSflags.GcFlags.heapSize * 100);
 #endif
 
-#if defined(PROMOTION_DATA)   /* For dead promote & premature promote data */
-       { char *promote_str[BIG_STRING_LEN];
-          sprintf(promote_str, " %6ld %6ld", dead_prom*sizeof(W_), dead_prev*sizeof(W_));
-         strcat(major_str, promote_str);
-        }
-#endif /* PROMOTION_DATA */
-
        stat_endGC(0, alloc, resident, major_str);
     } else { 
        stat_endGC(0, alloc, resident, "");
     }
 
-    if (SM_trace) {
+    if (RTSflags.GcFlags.trace) {
        fprintf(stderr, "Major: newbase 0x%lx newlim 0x%lx; base 0x%lx lim 0x%lx thresh 0x%lx max 0x%lx\n        hp 0x%lx, hplim 0x%lx, free %lu\n",
                (W_) appelInfo.newbase,   (W_) appelInfo.newlim,
                (W_) appelInfo.oldbase,   (W_) appelInfo.oldlim,