Commit f9d15f9f authored by Simon Marlow's avatar Simon Marlow

Store a destination step in the block descriptor

At the moment, this just saves a memory reference in the GC inner loop
(worth a percent or two of GC time).  Later, it will hopefully let me
experiment with partial steps, and simplifying the generation/step
infrastructure.
parent 9ca114a5
......@@ -48,22 +48,26 @@
#ifndef CMINUSMINUS
typedef struct bdescr_ {
StgPtr start; /* start addr of memory */
StgPtr free; /* first free byte of memory */
struct bdescr_ *link; /* used for chaining blocks together */
union {
struct bdescr_ *back; /* used (occasionally) for doubly-linked lists*/
StgWord *bitmap;
StgPtr scan; /* scan pointer for copying GC */
} u;
unsigned int gen_no; /* generation */
struct step_ *step; /* step */
StgWord32 blocks; /* no. of blocks (if grp head, 0 otherwise) */
StgWord32 flags; /* block is in to-space */
StgPtr start; /* start addr of memory */
StgPtr free; /* first free byte of memory */
struct bdescr_ *link; /* used for chaining blocks together */
union {
struct bdescr_ *back; /* used (occasionally) for doubly-linked lists*/
StgWord *bitmap;
StgPtr scan; /* scan pointer for copying GC */
} u;
struct step_ *step; /* step */
struct step_ *dest; /* destination step */
StgWord32 blocks; /* no. of blocks (if grp head, 0 otherwise) */
StgWord16 gen_no;
StgWord16 flags; /* block flags, see below */
#if SIZEOF_VOID_P == 8
StgWord32 _padding[2];
StgWord32 _padding[2];
#else
StgWord32 _padding[0];
StgWord32 _padding[0];
#endif
} bdescr;
#endif
......
......@@ -214,4 +214,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)
{
bd->step = step;
bd->gen_no = step->gen_no;
bd->dest = step->to;
}
#endif /* RTS_STORAGE_GC_H */
......@@ -86,6 +86,7 @@ arenaAlloc( Arena *arena, size_t size )
bd->gen_no = 0;
bd->step = NULL;
bd->dest = NULL;
bd->flags = 0;
bd->free = bd->start;
bd->link = arena->current;
......
......@@ -1118,8 +1118,8 @@ scheduleHandleHeapOverflow( Capability *cap, StgTSO *t )
{
bdescr *x;
for (x = bd; x < bd + blocks; x++) {
x->step = cap->r.rNursery;
x->gen_no = 0;
initBdescr(x,cap->r.rNursery);
x->free = x->start;
x->flags = 0;
}
}
......
......@@ -191,7 +191,7 @@ no_slop:
StgInd_indirectee(p1) = p2; \
prim %write_barrier() []; \
bd = Bdescr(p1); \
if (bdescr_gen_no(bd) != 0 :: CInt) { \
if (bdescr_gen_no(bd) != 0 :: bits16) { \
recordMutableCap(p1, TO_W_(bdescr_gen_no(bd)), R1); \
SET_INFO(p1, stg_IND_OLDGEN_info); \
LDV_RECORD_CREATE(p1); \
......
......@@ -59,6 +59,7 @@ static void initMBlock(void *mblock);
bd->flags
bd->gen_no
bd->step
bd->dest
Exceptions: we don't maintain invariants for all the blocks within a
group on the free list, because it is expensive to modify every
......
......@@ -282,8 +282,7 @@ evacuate_large(StgPtr p)
ws = &gct->steps[new_stp->abs_no];
bd->flags |= BF_EVACUATED;
bd->step = new_stp;
bd->gen_no = new_stp->gen_no;
initBdescr(bd, new_stp);
// If this is a block of pinned objects, we don't have to scan
// these objects, because they aren't allowed to contain any
......@@ -505,7 +504,7 @@ loop:
return;
}
stp = bd->step->to;
stp = bd->dest;
info = q->header.info;
if (IS_FORWARDING_PTR(info))
......@@ -1069,7 +1068,7 @@ bale_out:
// check whether it was updated in the meantime.
*q = (StgClosure *)p;
if (evac) {
copy(q,(const StgInfoTable *)info_ptr,(StgClosure *)p,THUNK_SELECTOR_sizeW(),bd->step->to);
copy(q,(const StgInfoTable *)info_ptr,(StgClosure *)p,THUNK_SELECTOR_sizeW(),bd->dest);
}
unchain_thunk_selectors(prev_thunk_selector, *q);
return;
......
......@@ -269,8 +269,7 @@ alloc_todo_block (step_workspace *ws, nat size)
} else {
bd = allocBlock_sync();
}
bd->step = ws->step;
bd->gen_no = ws->step->gen_no;
initBdescr(bd, ws->step);
bd->flags = BF_EVACUATED;
bd->u.scan = bd->free = bd->start;
}
......
......@@ -411,8 +411,7 @@ allocNursery (step *stp, bdescr *tail, nat blocks)
if (tail != NULL) {
tail->u.back = bd;
}
bd->step = stp;
bd->gen_no = 0;
initBdescr(bd, stp);
bd->flags = 0;
bd->free = bd->start;
tail = bd;
......@@ -612,8 +611,7 @@ allocateInGen (generation *g, lnat n)
dbl_link_onto(bd, &stp->large_objects);
stp->n_large_blocks += bd->blocks; // might be larger than req_blocks
alloc_blocks += bd->blocks;
bd->gen_no = g->no;
bd->step = stp;
initBdescr(bd, stp);
bd->flags = BF_LARGE;
bd->free = bd->start + n;
ret = bd->start;
......@@ -624,8 +622,7 @@ allocateInGen (generation *g, lnat n)
bd = stp->blocks;
if (bd == NULL || bd->free + n > bd->start + BLOCK_SIZE_W) {
bd = allocBlock();
bd->gen_no = g->no;
bd->step = stp;
initBdescr(bd, stp);
bd->flags = 0;
bd->link = stp->blocks;
stp->blocks = bd;
......@@ -676,8 +673,7 @@ splitLargeBlock (bdescr *bd, nat blocks)
dbl_link_onto(new_bd, &g0s0->large_objects);
g0s0->n_large_blocks += new_bd->blocks;
new_bd->gen_no = g0s0->no;
new_bd->step = g0s0;
initBdescr(new_bd, g0s0);
new_bd->flags = BF_LARGE;
new_bd->free = bd->free;
ASSERT(new_bd->free <= new_bd->start + new_bd->blocks * BLOCK_SIZE_W);
......@@ -733,8 +729,7 @@ allocateLocal (Capability *cap, lnat n)
bd = allocBlock();
cap->r.rNursery->n_blocks++;
RELEASE_SM_LOCK;
bd->gen_no = 0;
bd->step = cap->r.rNursery;
initBdescr(bd, cap->r.rNursery);
bd->flags = 0;
// NO: alloc_blocks++;
// calcAllocated() uses the size of the nursery, and we've
......@@ -807,8 +802,7 @@ allocatePinned( lnat n )
pinned_object_block = bd = allocBlock();
dbl_link_onto(bd, &g0s0->large_objects);
g0s0->n_large_blocks++;
bd->gen_no = 0;
bd->step = g0s0;
initBdescr(bd, g0s0);
bd->flags = BF_PINNED | BF_LARGE;
bd->free = bd->start;
alloc_blocks++;
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment