summaryrefslogtreecommitdiff
path: root/includes
diff options
context:
space:
mode:
authorSimon Marlow <marlowsd@gmail.com>2009-12-03 15:07:28 +0000
committerSimon Marlow <marlowsd@gmail.com>2009-12-03 15:07:28 +0000
commit214b3663d5d7598c13643f9221e43d5a7735b47f (patch)
treede779bab8dbcf057eaf481e6b612b63881e246e9 /includes
parent7cb1d9274e84ee2fc2dd610aa4f7686586ca0357 (diff)
downloadhaskell-214b3663d5d7598c13643f9221e43d5a7735b47f.tar.gz
GC refactoring, remove "steps"
The GC had a two-level structure, G generations each of T steps. Steps are for aging within a generation, mostly to avoid premature promotion. Measurements show that more than 2 steps is almost never worthwhile, and 1 step is usually worse than 2. In theory fractional steps are possible, so the ideal number of steps is somewhere between 1 and 3. GHC's default has always been 2. We can implement 2 steps quite straightforwardly by having each block point to the generation to which objects in that block should be promoted, so blocks in the nursery point to generation 0, and blocks in gen 0 point to gen 1, and so on. This commit removes the explicit step structures, merging generations with steps, thus simplifying a lot of code. Performance is unaffected. The tunable number of steps is now gone, although it may be replaced in the future by a way to tune the aging in generation 0.
Diffstat (limited to 'includes')
-rw-r--r--includes/Cmm.h2
-rw-r--r--includes/mkDerivedConstants.c3
-rw-r--r--includes/rts/storage/Block.h4
-rw-r--r--includes/rts/storage/GC.h67
-rw-r--r--includes/stg/Regs.h8
5 files changed, 36 insertions, 48 deletions
diff --git a/includes/Cmm.h b/includes/Cmm.h
index 59081e2466..6d39b45a39 100644
--- a/includes/Cmm.h
+++ b/includes/Cmm.h
@@ -385,7 +385,7 @@
// allocate() - this includes many of the primops.
#define MAYBE_GC(liveness,reentry) \
if (bdescr_link(CurrentNursery) == NULL || \
- step_n_large_blocks(StgRegTable_rNursery(BaseReg)) >= CInt[alloc_blocks_lim]) { \
+ generation_n_large_blocks(W_[g0]) >= CInt[alloc_blocks_lim]) { \
R9 = liveness; \
R10 = reentry; \
HpAlloc = 0; \
diff --git a/includes/mkDerivedConstants.c b/includes/mkDerivedConstants.c
index ddd2e65983..23a4ecd64e 100644
--- a/includes/mkDerivedConstants.c
+++ b/includes/mkDerivedConstants.c
@@ -249,8 +249,7 @@ main(int argc, char *argv[])
struct_size(generation);
struct_field(generation, mut_list);
-
- struct_field(step, n_large_blocks);
+ struct_field(generation, n_large_blocks);
struct_size(CostCentreStack);
struct_field(CostCentreStack, ccsID);
diff --git a/includes/rts/storage/Block.h b/includes/rts/storage/Block.h
index e99a03e76c..3114bea014 100644
--- a/includes/rts/storage/Block.h
+++ b/includes/rts/storage/Block.h
@@ -57,8 +57,8 @@ typedef struct bdescr_ {
StgPtr scan; /* scan pointer for copying GC */
} u;
- struct step_ *step; /* step */
- struct step_ *dest; /* destination step */
+ struct generation_ *gen; /* generation */
+ struct generation_ *dest; /* destination gen */
StgWord32 blocks; /* no. of blocks (if grp head, 0 otherwise) */
diff --git a/includes/rts/storage/GC.h b/includes/rts/storage/GC.h
index 1cd57c9045..e7b2e8453b 100644
--- a/includes/rts/storage/GC.h
+++ b/includes/rts/storage/GC.h
@@ -53,24 +53,32 @@
*
* ------------------------------------------------------------------------- */
-typedef struct step_ {
- unsigned int no; // step number in this generation
- unsigned int abs_no; // absolute step number
+typedef struct nursery_ {
+ bdescr * blocks;
+ unsigned int n_blocks;
+} nursery;
- struct generation_ * gen; // generation this step belongs to
- unsigned int gen_no; // generation number (cached)
-
- bdescr * blocks; // blocks in this step
- unsigned int n_blocks; // number of blocks
- unsigned int n_words; // number of words
+typedef struct generation_ {
+ unsigned int no; // generation number
- struct step_ * to; // destination step for live objects
+ bdescr * blocks; // blocks in this gen
+ unsigned int n_blocks; // number of blocks
+ unsigned int n_words; // number of words
- bdescr * large_objects; // large objects (doubly linked)
- unsigned int n_large_blocks; // no. of blocks used by large objs
+ bdescr * large_objects; // large objects (doubly linked)
+ unsigned int n_large_blocks; // no. of blocks used by large objs
- StgTSO * threads; // threads in this step
+ unsigned int max_blocks; // max blocks
+ bdescr *mut_list; // mut objects in this gen (not G0)
+
+ StgTSO * threads; // threads in this gen
// linked via global_link
+ struct generation_ *to; // destination gen for live objects
+
+ // stats information
+ unsigned int collections;
+ unsigned int par_collections;
+ unsigned int failed_promotions;
// ------------------------------------
// Fields below are used during GC only
@@ -85,13 +93,15 @@ typedef struct step_ {
int mark; // mark (not copy)? (old gen only)
int compact; // compact (not sweep)? (old gen only)
- // During GC, if we are collecting this step, blocks and n_blocks
+ // During GC, if we are collecting this gen, blocks and n_blocks
// are copied into the following two fields. After GC, these blocks
// are freed.
bdescr * old_blocks; // bdescr of first from-space block
unsigned int n_old_blocks; // number of blocks in from-space
unsigned int live_estimate; // for sweeping: estimate of live data
+ bdescr * saved_mut_list;
+
bdescr * part_blocks; // partially-full scanned blocks
unsigned int n_part_blocks; // count of above
@@ -101,32 +111,11 @@ typedef struct step_ {
bdescr * bitmap; // bitmap for compacting collection
StgTSO * old_threads;
-
-} step;
-
-
-typedef struct generation_ {
- unsigned int no; // generation number
- step * steps; // steps
- unsigned int n_steps; // number of steps
- unsigned int max_blocks; // max blocks in step 0
- bdescr *mut_list; // mut objects in this gen (not G0)
-
- // stats information
- unsigned int collections;
- unsigned int par_collections;
- unsigned int failed_promotions;
-
- // temporary use during GC:
- bdescr *saved_mut_list;
} generation;
extern generation * generations;
-
extern generation * g0;
extern generation * oldest_gen;
-extern step * all_steps;
-extern nat total_steps;
/* -----------------------------------------------------------------------------
Generic allocation
@@ -194,11 +183,11 @@ void dirty_MUT_VAR(StgRegTable *reg, StgClosure *p);
/* (needed when dynamic libraries are used). */
extern rtsBool keepCAFs;
-INLINE_HEADER void initBdescr(bdescr *bd, step *step)
+INLINE_HEADER void initBdescr(bdescr *bd, generation *gen, generation *dest)
{
- bd->step = step;
- bd->gen_no = step->gen_no;
- bd->dest = step->to;
+ bd->gen = gen;
+ bd->gen_no = gen->no;
+ bd->dest = dest;
}
#endif /* RTS_STORAGE_GC_H */
diff --git a/includes/stg/Regs.h b/includes/stg/Regs.h
index d620bf1466..e50b431d14 100644
--- a/includes/stg/Regs.h
+++ b/includes/stg/Regs.h
@@ -80,10 +80,10 @@ typedef struct StgRegTable_ {
StgPtr rSpLim;
StgPtr rHp;
StgPtr rHpLim;
- struct StgTSO_ *rCurrentTSO;
- struct step_ *rNursery;
- struct bdescr_ *rCurrentNursery; /* Hp/HpLim point into this block */
- struct bdescr_ *rCurrentAlloc; /* for allocation using allocate() */
+ struct StgTSO_ * rCurrentTSO;
+ struct nursery_ * rNursery;
+ struct bdescr_ * rCurrentNursery; /* Hp/HpLim point into this block */
+ struct bdescr_ * rCurrentAlloc; /* for allocation using allocate() */
StgWord rHpAlloc; /* number of *bytes* being allocated in heap */
StgWord rRet; // holds the return code of the thread
} StgRegTable;