summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--rts/RetainerProfile.c331
1 files changed, 170 insertions, 161 deletions
diff --git a/rts/RetainerProfile.c b/rts/RetainerProfile.c
index 79aade9c44..8eeda7ce1a 100644
--- a/rts/RetainerProfile.c
+++ b/rts/RetainerProfile.c
@@ -93,14 +93,6 @@ StgWord flip = 0; // flip bit
#define setRetainerSetToNull(c) \
(c)->header.prof.hp.rs = (RetainerSet *)((StgWord)NULL | flip)
-static void retainStack(StgClosure *, retainer, StgPtr, StgPtr);
-static void retainClosure(StgClosure *, StgClosure *, retainer);
-#if defined(DEBUG_RETAINER)
-static void belongToHeap(StgPtr p);
-static uint32_t checkHeapSanityForRetainerProfiling( void );
-#endif
-static void retainPushClosure( StgClosure *p, StgClosure *c, retainer c_child_r);
-
#if defined(DEBUG_RETAINER)
static uint32_t sumOfNewCost; // sum of the cost of each object, computed
// when the object is first visited
@@ -175,8 +167,7 @@ typedef struct {
stackPos info;
} stackElement;
-static void retainActualPush( stackElement *se);
-
+typedef struct {
/*
Invariants:
firstStack points to the first block group.
@@ -194,9 +185,9 @@ static void retainActualPush( stackElement *se);
the topmost element on the previous block group so as to satisfy
the invariants described above.
*/
-static bdescr *firstStack = NULL;
-static bdescr *currentStack;
-static stackElement *stackBottom, *stackTop, *stackLimit;
+ bdescr *firstStack;
+ bdescr *currentStack;
+ stackElement *stackBottom, *stackTop, *stackLimit;
/*
currentStackBoundary is used to mark the current stack chunk.
@@ -204,7 +195,7 @@ static stackElement *stackBottom, *stackTop, *stackLimit;
is empty. It is the responsibility of the user to keep currentStackBoundary
valid all the time if it is to be employed.
*/
-static stackElement *currentStackBoundary;
+ stackElement *currentStackBoundary;
#if defined(DEBUG_RETAINER)
/*
@@ -219,8 +210,23 @@ static stackElement *currentStackBoundary;
retainer profiling, maxStackSize is some value no greater
than the actual depth of the graph.
*/
-static int stackSize, maxStackSize;
+ int stackSize, maxStackSize;
#endif
+} traverseState;
+
+traverseState g_retainerTraverseState;
+
+
+static void retainStack(traverseState *, StgClosure *, retainer, StgPtr, StgPtr);
+static void retainClosure(traverseState *, StgClosure *, StgClosure *, retainer);
+static void retainPushClosure(traverseState *, StgClosure *, StgClosure *, retainer);
+static void retainActualPush(traverseState *, stackElement *);
+
+#if defined(DEBUG_RETAINER)
+static void belongToHeap(StgPtr p);
+static uint32_t checkHeapSanityForRetainerProfiling( void );
+#endif
+
// number of blocks allocated for one stack
#define BLOCKS_IN_STACK 1
@@ -231,13 +237,13 @@ static int stackSize, maxStackSize;
* currentStack->link == s.
* -------------------------------------------------------------------------- */
static INLINE void
-newStackBlock( bdescr *bd )
+newStackBlock( traverseState *ts, bdescr *bd )
{
- currentStack = bd;
- stackTop = (stackElement *)(bd->start + BLOCK_SIZE_W * bd->blocks);
- stackBottom = (stackElement *)bd->start;
- stackLimit = (stackElement *)stackTop;
- bd->free = (StgPtr)stackLimit;
+ ts->currentStack = bd;
+ ts->stackTop = (stackElement *)(bd->start + BLOCK_SIZE_W * bd->blocks);
+ ts->stackBottom = (stackElement *)bd->start;
+ ts->stackLimit = (stackElement *)ts->stackTop;
+ bd->free = (StgPtr)ts->stackLimit;
}
/* -----------------------------------------------------------------------------
@@ -246,30 +252,30 @@ newStackBlock( bdescr *bd )
* s->link == currentStack.
* -------------------------------------------------------------------------- */
static INLINE void
-returnToOldStack( bdescr *bd )
+returnToOldStack( traverseState *ts, bdescr *bd )
{
- currentStack = bd;
- stackTop = (stackElement *)bd->free;
- stackBottom = (stackElement *)bd->start;
- stackLimit = (stackElement *)(bd->start + BLOCK_SIZE_W * bd->blocks);
- bd->free = (StgPtr)stackLimit;
+ ts->currentStack = bd;
+ ts->stackTop = (stackElement *)bd->free;
+ ts->stackBottom = (stackElement *)bd->start;
+ ts->stackLimit = (stackElement *)(bd->start + BLOCK_SIZE_W * bd->blocks);
+ bd->free = (StgPtr)ts->stackLimit;
}
/* -----------------------------------------------------------------------------
* Initializes the traverse stack.
* -------------------------------------------------------------------------- */
static void
-initializeTraverseStack( void )
+initializeTraverseStack( traverseState *ts )
{
- if (firstStack != NULL) {
- freeChain(firstStack);
+ if (ts->firstStack != NULL) {
+ freeChain(ts->firstStack);
}
- firstStack = allocGroup(BLOCKS_IN_STACK);
- firstStack->link = NULL;
- firstStack->u.back = NULL;
+ ts->firstStack = allocGroup(BLOCKS_IN_STACK);
+ ts->firstStack->link = NULL;
+ ts->firstStack->u.back = NULL;
- newStackBlock(firstStack);
+ newStackBlock(ts, ts->firstStack);
}
/* -----------------------------------------------------------------------------
@@ -278,19 +284,19 @@ initializeTraverseStack( void )
* firstStack != NULL
* -------------------------------------------------------------------------- */
static void
-closeTraverseStack( void )
+closeTraverseStack( traverseState *ts )
{
- freeChain(firstStack);
- firstStack = NULL;
+ freeChain(ts->firstStack);
+ ts->firstStack = NULL;
}
/* -----------------------------------------------------------------------------
* Returns true if the whole stack is empty.
* -------------------------------------------------------------------------- */
static INLINE bool
-isEmptyRetainerStack( void )
+isEmptyRetainerStack( traverseState *ts )
{
- return (firstStack == currentStack) && stackTop == stackLimit;
+ return (ts->firstStack == ts->currentStack) && ts->stackTop == ts->stackLimit;
}
/* -----------------------------------------------------------------------------
@@ -301,8 +307,9 @@ retainerStackBlocks( void )
{
bdescr* bd;
W_ res = 0;
+ traverseState *ts = &g_retainerTraverseState;
- for (bd = firstStack; bd != NULL; bd = bd->link)
+ for (bd = ts->firstStack; bd != NULL; bd = bd->link)
res += bd->blocks;
return res;
@@ -313,9 +320,9 @@ retainerStackBlocks( void )
* i.e., if the current stack chunk is empty.
* -------------------------------------------------------------------------- */
static INLINE bool
-isOnBoundary( void )
+isOnBoundary( traverseState *ts )
{
- return stackTop == currentStackBoundary;
+ return ts->stackTop == ts->currentStackBoundary;
}
/* -----------------------------------------------------------------------------
@@ -388,40 +395,40 @@ find_srt( stackPos *info )
* Pushes an element onto traverse stack
* -------------------------------------------------------------------------- */
static void
-retainActualPush(stackElement *se) {
+retainActualPush(traverseState *ts, stackElement *se) {
bdescr *nbd; // Next Block Descriptor
- if (stackTop - 1 < stackBottom) {
+ if (ts->stackTop - 1 < ts->stackBottom) {
#if defined(DEBUG_RETAINER)
// debugBelch("push() to the next stack.\n");
#endif
// currentStack->free is updated when the active stack is switched
// to the next stack.
- currentStack->free = (StgPtr)stackTop;
+ ts->currentStack->free = (StgPtr)ts->stackTop;
- if (currentStack->link == NULL) {
+ if (ts->currentStack->link == NULL) {
nbd = allocGroup(BLOCKS_IN_STACK);
nbd->link = NULL;
- nbd->u.back = currentStack;
- currentStack->link = nbd;
+ nbd->u.back = ts->currentStack;
+ ts->currentStack->link = nbd;
} else
- nbd = currentStack->link;
+ nbd = ts->currentStack->link;
- newStackBlock(nbd);
+ newStackBlock(ts, nbd);
}
// adjust stackTop (acutal push)
- stackTop--;
+ ts->stackTop--;
// If the size of stackElement was huge, we would better replace the
// following statement by either a memcpy() call or a switch statement
// on the type of the element. Currently, the size of stackElement is
// small enough (5 words) that this direct assignment seems to be enough.
- *stackTop = *se;
+ *ts->stackTop = *se;
#if defined(DEBUG_RETAINER)
- stackSize++;
- if (stackSize > maxStackSize) maxStackSize = stackSize;
- ASSERT(stackSize >= 0);
- debugBelch("stackSize = %d\n", stackSize);
+ ts->stackSize++;
+ if (ts->stackSize > ts->maxStackSize) ts->maxStackSize = ts->stackSize;
+ ASSERT(ts->stackSize >= 0);
+ debugBelch("stackSize = %d\n", ts->stackSize);
#endif
}
@@ -435,7 +442,7 @@ retainActualPush(stackElement *se) {
* c_child_r - closure retainer.
*/
static INLINE void
-retainPushClosure( StgClosure *c, StgClosure *p, retainer c_child_r) {
+retainPushClosure( traverseState *ts, StgClosure *c, StgClosure *p, retainer c_child_r) {
stackElement se;
se.c = c;
@@ -443,7 +450,7 @@ retainPushClosure( StgClosure *c, StgClosure *p, retainer c_child_r) {
se.info.next.parent = p;
se.info.type = posTypeFresh;
- retainActualPush(&se);
+ retainActualPush(ts, &se);
};
/* -----------------------------------------------------------------------------
@@ -462,13 +469,13 @@ retainPushClosure( StgClosure *c, StgClosure *p, retainer c_child_r) {
* Note: SRTs are considered to be children as well.
* -------------------------------------------------------------------------- */
static INLINE void
-push( StgClosure *c, retainer c_child_r, StgClosure **first_child )
+push( traverseState *ts, StgClosure *c, retainer c_child_r, StgClosure **first_child )
{
stackElement se;
bdescr *nbd; // Next Block Descriptor
#if defined(DEBUG_RETAINER)
- debugBelch("push(): stackTop = 0x%x, currentStackBoundary = 0x%x\n", stackTop, currentStackBoundary);
+ debugBelch("push(): stackTop = 0x%x, currentStackBoundary = 0x%x\n", ts->stackTop, ts->currentStackBoundary);
#endif
ASSERT(get_itbl(c)->type != TSO);
@@ -661,7 +668,7 @@ push( StgClosure *c, retainer c_child_r, StgClosure **first_child )
return;
}
- retainActualPush(&se);
+ retainActualPush(ts, &se);
}
/* -----------------------------------------------------------------------------
@@ -678,7 +685,7 @@ push( StgClosure *c, retainer c_child_r, StgClosure **first_child )
* is called only within popOff() and nowhere else.
* -------------------------------------------------------------------------- */
static void
-popOffReal(void)
+popOffReal(traverseState *ts)
{
bdescr *pbd; // Previous Block Descriptor
@@ -686,62 +693,62 @@ popOffReal(void)
debugBelch("pop() to the previous stack.\n");
#endif
- ASSERT(stackTop + 1 == stackLimit);
- ASSERT(stackBottom == (stackElement *)currentStack->start);
+ ASSERT(ts->stackTop + 1 == ts->stackLimit);
+ ASSERT(ts->stackBottom == (stackElement *)ts->currentStack->start);
- if (firstStack == currentStack) {
+ if (ts->firstStack == ts->currentStack) {
// The stack is completely empty.
- stackTop++;
- ASSERT(stackTop == stackLimit);
+ ts->stackTop++;
+ ASSERT(ts->stackTop == ts->stackLimit);
#if defined(DEBUG_RETAINER)
- stackSize--;
- if (stackSize > maxStackSize) maxStackSize = stackSize;
- ASSERT(stackSize >= 0);
- debugBelch("stackSize = %d\n", stackSize);
+ ts->stackSize--;
+ if (ts->stackSize > ts->maxStackSize) ts->maxStackSize = ts->stackSize;
+ ASSERT(ts->stackSize >= 0);
+ debugBelch("stackSize = %d\n", ts->stackSize);
#endif
return;
}
// currentStack->free is updated when the active stack is switched back
// to the previous stack.
- currentStack->free = (StgPtr)stackLimit;
+ ts->currentStack->free = (StgPtr)ts->stackLimit;
// find the previous block descriptor
- pbd = currentStack->u.back;
+ pbd = ts->currentStack->u.back;
ASSERT(pbd != NULL);
- returnToOldStack(pbd);
+ returnToOldStack(ts, pbd);
#if defined(DEBUG_RETAINER)
- stackSize--;
- if (stackSize > maxStackSize) maxStackSize = stackSize;
- ASSERT(stackSize >= 0);
- debugBelch("stackSize = %d\n", stackSize);
+ ts->stackSize--;
+ if (ts->stackSize > ts->maxStackSize) ts->maxStackSize = ts->stackSize;
+ ASSERT(ts->stackSize >= 0);
+ debugBelch("stackSize = %d\n", ts->stackSize);
#endif
}
static INLINE void
-popOff(void) {
+popOff(traverseState *ts) {
#if defined(DEBUG_RETAINER)
- debugBelch("\tpopOff(): stackTop = 0x%x, currentStackBoundary = 0x%x\n", stackTop, currentStackBoundary);
+ debugBelch("\tpopOff(): stackTop = 0x%x, currentStackBoundary = 0x%x\n", ts->stackTop, ts->currentStackBoundary);
#endif
- ASSERT(stackTop != stackLimit);
- ASSERT(!isEmptyRetainerStack());
+ ASSERT(ts->stackTop != ts->stackLimit);
+ ASSERT(!isEmptyRetainerStack(ts));
// <= (instead of <) is wrong!
- if (stackTop + 1 < stackLimit) {
- stackTop++;
+ if (ts->stackTop + 1 < ts->stackLimit) {
+ ts->stackTop++;
#if defined(DEBUG_RETAINER)
- stackSize--;
- if (stackSize > maxStackSize) maxStackSize = stackSize;
- ASSERT(stackSize >= 0);
- debugBelch("stackSize = %d\n", stackSize);
+ ts->stackSize--;
+ if (ts->stackSize > ts->maxStackSize) ts->maxStackSize = ts->stackSize;
+ ASSERT(ts->stackSize >= 0);
+ debugBelch("stackSize = %d\n", ts->stackSize);
#endif
return;
}
- popOffReal();
+ popOffReal(ts);
}
/* -----------------------------------------------------------------------------
@@ -763,28 +770,28 @@ popOff(void) {
* is empty.
* -------------------------------------------------------------------------- */
static INLINE void
-pop( StgClosure **c, StgClosure **cp, retainer *r )
+pop( traverseState *ts, StgClosure **c, StgClosure **cp, retainer *r )
{
stackElement *se;
#if defined(DEBUG_RETAINER)
- debugBelch("pop(): stackTop = 0x%x, currentStackBoundary = 0x%x\n", stackTop, currentStackBoundary);
+ debugBelch("pop(): stackTop = 0x%x, currentStackBoundary = 0x%x\n", ts->stackTop, ts->currentStackBoundary);
#endif
do {
- if (isOnBoundary()) { // if the current stack chunk is depleted
+ if (isOnBoundary(ts)) { // if the current stack chunk is depleted
*c = NULL;
return;
}
- se = stackTop;
+ se = ts->stackTop;
// If this is a top-level element, you should pop that out.
if (se->info.type == posTypeFresh) {
*cp = se->info.next.parent;
*c = se->c;
*r = se->c_child_r;
- popOff();
+ popOff(ts);
return;
}
@@ -795,7 +802,7 @@ pop( StgClosure **c, StgClosure **cp, retainer *r )
*c = se->c->payload[1];
*cp = se->c;
*r = se->c_child_r;
- popOff();
+ popOff(ts);
return;
// three children (fixed), no SRT
@@ -808,7 +815,7 @@ pop( StgClosure **c, StgClosure **cp, retainer *r )
// no popOff
} else {
*c = ((StgMVar *)se->c)->value;
- popOff();
+ popOff(ts);
}
*cp = se->c;
*r = se->c_child_r;
@@ -822,7 +829,7 @@ pop( StgClosure **c, StgClosure **cp, retainer *r )
// no popOff
} else {
*c = ((StgWeak *)se->c)->finalizer;
- popOff();
+ popOff(ts);
}
*cp = se->c;
*r = se->c_child_r;
@@ -839,7 +846,7 @@ pop( StgClosure **c, StgClosure **cp, retainer *r )
uint32_t field_no = se->info.next.step & 3;
if (entry_no == ((StgTRecChunk *)se->c)->next_entry_idx) {
*c = NULL;
- popOff();
+ popOff(ts);
break;
}
entry = &((StgTRecChunk *)se->c)->entries[entry_no];
@@ -872,7 +879,7 @@ pop( StgClosure **c, StgClosure **cp, retainer *r )
case SMALL_MUT_ARR_PTRS_FROZEN_DIRTY:
*c = find_ptrs(&se->info);
if (*c == NULL) {
- popOff();
+ popOff(ts);
break;
}
*cp = se->c;
@@ -924,7 +931,7 @@ pop( StgClosure **c, StgClosure **cp, retainer *r )
*r = se->c_child_r;
return;
}
- popOff();
+ popOff(ts);
break;
// no child (fixed), no SRT
@@ -1169,8 +1176,8 @@ associate( StgClosure *c, RetainerSet *s )
-------------------------------------------------------------------------- */
static void
-retain_large_bitmap (StgPtr p, StgLargeBitmap *large_bitmap, uint32_t size,
- StgClosure *c, retainer c_child_r)
+retain_large_bitmap (traverseState *ts, StgPtr p, StgLargeBitmap *large_bitmap,
+ uint32_t size, StgClosure *c, retainer c_child_r)
{
uint32_t i, b;
StgWord bitmap;
@@ -1179,7 +1186,7 @@ retain_large_bitmap (StgPtr p, StgLargeBitmap *large_bitmap, uint32_t size,
bitmap = large_bitmap->bitmap[b];
for (i = 0; i < size; ) {
if ((bitmap & 1) == 0) {
- retainPushClosure((StgClosure *)*p, c, c_child_r);
+ retainPushClosure(ts, (StgClosure *)*p, c, c_child_r);
}
i++;
p++;
@@ -1193,12 +1200,12 @@ retain_large_bitmap (StgPtr p, StgLargeBitmap *large_bitmap, uint32_t size,
}
static INLINE StgPtr
-retain_small_bitmap (StgPtr p, uint32_t size, StgWord bitmap,
+retain_small_bitmap (traverseState *ts, StgPtr p, uint32_t size, StgWord bitmap,
StgClosure *c, retainer c_child_r)
{
while (size > 0) {
if ((bitmap & 1) == 0) {
- retainPushClosure((StgClosure *)*p, c, c_child_r);
+ retainPushClosure(ts, (StgClosure *)*p, c, c_child_r);
}
p++;
bitmap = bitmap >> 1;
@@ -1226,7 +1233,7 @@ retain_small_bitmap (StgPtr p, uint32_t size, StgWord bitmap,
* retainPushClosure() is invoked instead of evacuate().
* -------------------------------------------------------------------------- */
static void
-retainStack( StgClosure *c, retainer c_child_r,
+retainStack( traverseState *ts, StgClosure *c, retainer c_child_r,
StgPtr stackStart, StgPtr stackEnd )
{
stackElement *oldStackBoundary;
@@ -1241,12 +1248,12 @@ retainStack( StgClosure *c, retainer c_child_r,
record the current currentStackBoundary, which will be restored
at the exit.
*/
- oldStackBoundary = currentStackBoundary;
- currentStackBoundary = stackTop;
+ oldStackBoundary = ts->currentStackBoundary;
+ ts->currentStackBoundary = ts->stackTop;
#if defined(DEBUG_RETAINER)
debugBelch("retainStack() called: oldStackBoundary = 0x%x, currentStackBoundary = 0x%x\n",
- oldStackBoundary, currentStackBoundary);
+ oldStackBoundary, ts->currentStackBoundary);
#endif
ASSERT(get_itbl(c)->type == STACK);
@@ -1258,7 +1265,7 @@ retainStack( StgClosure *c, retainer c_child_r,
switch(info->i.type) {
case UPDATE_FRAME:
- retainPushClosure(((StgUpdateFrame *)p)->updatee, c, c_child_r);
+ retainPushClosure(ts, ((StgUpdateFrame *)p)->updatee, c, c_child_r);
p += sizeofW(StgUpdateFrame);
continue;
@@ -1272,11 +1279,11 @@ retainStack( StgClosure *c, retainer c_child_r,
bitmap = BITMAP_BITS(info->i.layout.bitmap);
size = BITMAP_SIZE(info->i.layout.bitmap);
p++;
- p = retain_small_bitmap(p, size, bitmap, c, c_child_r);
+ p = retain_small_bitmap(ts, p, size, bitmap, c, c_child_r);
follow_srt:
if (info->i.srt) {
- retainPushClosure(GET_SRT(info), c, c_child_r);
+ retainPushClosure(ts, GET_SRT(info), c, c_child_r);
}
continue;
@@ -1284,11 +1291,11 @@ retainStack( StgClosure *c, retainer c_child_r,
StgBCO *bco;
p++;
- retainPushClosure((StgClosure*)*p, c, c_child_r);
+ retainPushClosure(ts, (StgClosure*)*p, c, c_child_r);
bco = (StgBCO *)*p;
p++;
size = BCO_BITMAP_SIZE(bco);
- retain_large_bitmap(p, BCO_BITMAP(bco), size, c, c_child_r);
+ retain_large_bitmap(ts, p, BCO_BITMAP(bco), size, c, c_child_r);
p += size;
continue;
}
@@ -1297,7 +1304,7 @@ retainStack( StgClosure *c, retainer c_child_r,
case RET_BIG:
size = GET_LARGE_BITMAP(&info->i)->size;
p++;
- retain_large_bitmap(p, GET_LARGE_BITMAP(&info->i),
+ retain_large_bitmap(ts, p, GET_LARGE_BITMAP(&info->i),
size, c, c_child_r);
p += size;
// and don't forget to follow the SRT
@@ -1307,7 +1314,7 @@ retainStack( StgClosure *c, retainer c_child_r,
StgRetFun *ret_fun = (StgRetFun *)p;
const StgFunInfoTable *fun_info;
- retainPushClosure(ret_fun->fun, c, c_child_r);
+ retainPushClosure(ts, ret_fun->fun, c, c_child_r);
fun_info = get_fun_itbl(UNTAG_CONST_CLOSURE(ret_fun->fun));
p = (P_)&ret_fun->payload;
@@ -1315,18 +1322,18 @@ retainStack( StgClosure *c, retainer c_child_r,
case ARG_GEN:
bitmap = BITMAP_BITS(fun_info->f.b.bitmap);
size = BITMAP_SIZE(fun_info->f.b.bitmap);
- p = retain_small_bitmap(p, size, bitmap, c, c_child_r);
+ p = retain_small_bitmap(ts, p, size, bitmap, c, c_child_r);
break;
case ARG_GEN_BIG:
size = GET_FUN_LARGE_BITMAP(fun_info)->size;
- retain_large_bitmap(p, GET_FUN_LARGE_BITMAP(fun_info),
+ retain_large_bitmap(ts, p, GET_FUN_LARGE_BITMAP(fun_info),
size, c, c_child_r);
p += size;
break;
default:
bitmap = BITMAP_BITS(stg_arg_bitmaps[fun_info->f.fun_type]);
size = BITMAP_SIZE(stg_arg_bitmaps[fun_info->f.fun_type]);
- p = retain_small_bitmap(p, size, bitmap, c, c_child_r);
+ p = retain_small_bitmap(ts, p, size, bitmap, c, c_child_r);
break;
}
goto follow_srt;
@@ -1339,10 +1346,10 @@ retainStack( StgClosure *c, retainer c_child_r,
}
// restore currentStackBoundary
- currentStackBoundary = oldStackBoundary;
+ ts->currentStackBoundary = oldStackBoundary;
#if defined(DEBUG_RETAINER)
debugBelch("retainStack() finished: currentStackBoundary = 0x%x\n",
- currentStackBoundary);
+ ts->currentStackBoundary);
#endif
}
@@ -1351,7 +1358,8 @@ retainStack( StgClosure *c, retainer c_child_r,
* ------------------------------------------------------------------------- */
static INLINE StgPtr
-retain_PAP_payload (StgClosure *pap, /* NOT tagged */
+retain_PAP_payload (traverseState *ts,
+ StgClosure *pap, /* NOT tagged */
retainer c_child_r, /* NOT tagged */
StgClosure *fun, /* tagged */
StgClosure** payload, StgWord n_args)
@@ -1360,7 +1368,7 @@ retain_PAP_payload (StgClosure *pap, /* NOT tagged */
StgWord bitmap;
const StgFunInfoTable *fun_info;
- retainPushClosure(fun, pap, c_child_r);
+ retainPushClosure(ts, fun, pap, c_child_r);
fun = UNTAG_CLOSURE(fun);
fun_info = get_fun_itbl(fun);
ASSERT(fun_info->i.type != PAP);
@@ -1370,22 +1378,22 @@ retain_PAP_payload (StgClosure *pap, /* NOT tagged */
switch (fun_info->f.fun_type) {
case ARG_GEN:
bitmap = BITMAP_BITS(fun_info->f.b.bitmap);
- p = retain_small_bitmap(p, n_args, bitmap,
+ p = retain_small_bitmap(ts, p, n_args, bitmap,
pap, c_child_r);
break;
case ARG_GEN_BIG:
- retain_large_bitmap(p, GET_FUN_LARGE_BITMAP(fun_info),
+ retain_large_bitmap(ts, p, GET_FUN_LARGE_BITMAP(fun_info),
n_args, pap, c_child_r);
p += n_args;
break;
case ARG_BCO:
- retain_large_bitmap((StgPtr)payload, BCO_BITMAP(fun),
+ retain_large_bitmap(ts, (StgPtr)payload, BCO_BITMAP(fun),
n_args, pap, c_child_r);
p += n_args;
break;
default:
bitmap = BITMAP_BITS(stg_arg_bitmaps[fun_info->f.fun_type]);
- p = retain_small_bitmap(p, n_args, bitmap, pap, c_child_r);
+ p = retain_small_bitmap(ts, p, n_args, bitmap, pap, c_child_r);
break;
}
return p;
@@ -1408,7 +1416,7 @@ retain_PAP_payload (StgClosure *pap, /* NOT tagged */
* *c0 can be TSO (as well as AP_STACK).
* -------------------------------------------------------------------------- */
static void
-retainClosure( StgClosure *c0, StgClosure *cp0, retainer r0 )
+retainClosure( traverseState *ts, StgClosure *c0, StgClosure *cp0, retainer r0 )
{
// c = Current closure (possibly tagged)
// cp = Current closure's Parent (NOT tagged)
@@ -1419,14 +1427,14 @@ retainClosure( StgClosure *c0, StgClosure *cp0, retainer r0 )
RetainerSet *s, *retainerSetOfc;
retainer r, c_child_r;
StgWord typeOfc;
- retainPushClosure(c0, cp0, r0);
+ retainPushClosure(ts, c0, cp0, r0);
#if defined(DEBUG_RETAINER)
StgPtr oldStackTop;
#endif
#if defined(DEBUG_RETAINER)
- oldStackTop = stackTop;
+ oldStackTop = ts->stackTop;
debugBelch("retainClosure() called: c0 = 0x%x, cp0 = 0x%x, r0 = 0x%x\n"
, c0, cp0, r0);
#endif
@@ -1436,12 +1444,12 @@ loop:
debugBelch("loop");
#endif
// pop to (c, cp, r);
- pop(&c, &cp, &r);
+ pop(ts, &c, &cp, &r);
if (c == NULL) {
#if defined(DEBUG_RETAINER)
debugBelch("retainClosure() ends: oldStackTop = 0x%x,stackTop = 0x%x\n",
- oldStackTop, stackTop);
+ oldStackTop, ts->stackTop);
#endif
return;
}
@@ -1615,7 +1623,7 @@ inner_loop:
// would be hard.
switch (typeOfc) {
case STACK:
- retainStack(c, c_child_r,
+ retainStack(ts, c, c_child_r,
((StgStack *)c)->sp,
((StgStack *)c)->stack + ((StgStack *)c)->stack_size);
goto loop;
@@ -1624,16 +1632,16 @@ inner_loop:
{
StgTSO *tso = (StgTSO *)c;
- retainPushClosure((StgClosure *) tso->stackobj, c, c_child_r);
- retainPushClosure((StgClosure *) tso->blocked_exceptions, c, c_child_r);
- retainPushClosure((StgClosure *) tso->bq, c, c_child_r);
- retainPushClosure((StgClosure *) tso->trec, c, c_child_r);
+ retainPushClosure(ts, (StgClosure *) tso->stackobj, c, c_child_r);
+ retainPushClosure(ts, (StgClosure *) tso->blocked_exceptions, c, c_child_r);
+ retainPushClosure(ts, (StgClosure *) tso->bq, c, c_child_r);
+ retainPushClosure(ts, (StgClosure *) tso->trec, c, c_child_r);
if ( tso->why_blocked == BlockedOnMVar
|| tso->why_blocked == BlockedOnMVarRead
|| tso->why_blocked == BlockedOnBlackHole
|| tso->why_blocked == BlockedOnMsgThrowTo
) {
- retainPushClosure(tso->block_info.closure, c, c_child_r);
+ retainPushClosure(ts, tso->block_info.closure, c, c_child_r);
}
goto loop;
}
@@ -1641,36 +1649,36 @@ inner_loop:
case BLOCKING_QUEUE:
{
StgBlockingQueue *bq = (StgBlockingQueue *)c;
- retainPushClosure((StgClosure *) bq->link, c, c_child_r);
- retainPushClosure((StgClosure *) bq->bh, c, c_child_r);
- retainPushClosure((StgClosure *) bq->owner, c, c_child_r);
+ retainPushClosure(ts, (StgClosure *) bq->link, c, c_child_r);
+ retainPushClosure(ts, (StgClosure *) bq->bh, c, c_child_r);
+ retainPushClosure(ts, (StgClosure *) bq->owner, c, c_child_r);
goto loop;
}
case PAP:
{
StgPAP *pap = (StgPAP *)c;
- retain_PAP_payload(c, c_child_r, pap->fun, pap->payload, pap->n_args);
+ retain_PAP_payload(ts, c, c_child_r, pap->fun, pap->payload, pap->n_args);
goto loop;
}
case AP:
{
StgAP *ap = (StgAP *)c;
- retain_PAP_payload(c, c_child_r, ap->fun, ap->payload, ap->n_args);
+ retain_PAP_payload(ts, c, c_child_r, ap->fun, ap->payload, ap->n_args);
goto loop;
}
case AP_STACK:
- retainPushClosure(((StgAP_STACK *)c)->fun, c, c_child_r);
- retainStack(c, c_child_r,
+ retainPushClosure(ts, ((StgAP_STACK *)c)->fun, c, c_child_r);
+ retainStack(ts, c, c_child_r,
(StgPtr)((StgAP_STACK *)c)->payload,
(StgPtr)((StgAP_STACK *)c)->payload +
((StgAP_STACK *)c)->size);
goto loop;
}
- push(c, c_child_r, &first_child);
+ push(ts, c, c_child_r, &first_child);
// If first_child is null, c has no child.
// If first_child is not null, the top stack element points to the next
@@ -1689,22 +1697,23 @@ inner_loop:
* Compute the retainer set for every object reachable from *tl.
* -------------------------------------------------------------------------- */
static void
-retainRoot(void *user STG_UNUSED, StgClosure **tl)
+retainRoot(void *user, StgClosure **tl)
{
+ traverseState *ts = (traverseState*) user;
StgClosure *c;
// We no longer assume that only TSOs and WEAKs are roots; any closure can
// be a root.
- ASSERT(isEmptyRetainerStack());
- currentStackBoundary = stackTop;
+ ASSERT(isEmptyRetainerStack(ts));
+ ts->currentStackBoundary = ts->stackTop;
c = UNTAG_CLOSURE(*tl);
maybeInitRetainerSet(c);
if (c != &stg_END_TSO_QUEUE_closure && isRetainer(c)) {
- retainClosure(c, c, getRetainerFrom(c));
+ retainClosure(ts, c, c, getRetainerFrom(c));
} else {
- retainClosure(c, c, CCS_SYSTEM);
+ retainClosure(ts, c, c, CCS_SYSTEM);
}
// NOT TRUE: ASSERT(isMember(getRetainerFrom(*tl), retainerSetOf(*tl)));
@@ -1716,7 +1725,7 @@ retainRoot(void *user STG_UNUSED, StgClosure **tl)
* Compute the retainer set for each of the objects in the heap.
* -------------------------------------------------------------------------- */
static void
-computeRetainerSet( void )
+computeRetainerSet( traverseState *ts )
{
StgWeak *weak;
uint32_t g, n;
@@ -1727,7 +1736,7 @@ computeRetainerSet( void )
RetainerSet tmpRetainerSet;
#endif
- markCapabilities(retainRoot, NULL); // for scheduler roots
+ markCapabilities(retainRoot, (void*)ts); // for scheduler roots
// This function is called after a major GC, when key, value, and finalizer
// all are guaranteed to be valid, or reachable.
@@ -1743,12 +1752,12 @@ computeRetainerSet( void )
for (g = 0; g < RtsFlags.GcFlags.generations; g++) {
for (weak = generations[g].weak_ptr_list; weak != NULL; weak = weak->link) {
// retainRoot((StgClosure *)weak);
- retainRoot(NULL, (StgClosure **)&weak);
+ retainRoot((void*)ts, (StgClosure **)&weak);
}
}
// Consider roots from the stable ptr table.
- markStablePtrTable(retainRoot, NULL);
+ markStablePtrTable(retainRoot, (void*)ts);
// Remember old stable name addresses.
rememberOldStableNameAddresses ();
@@ -1923,8 +1932,8 @@ retainerProfile(void)
flip = flip ^ 1;
#if defined(DEBUG_RETAINER)
- stackSize = 0;
- maxStackSize = 0;
+ g_retainerTraverseState.stackSize = 0;
+ g_retainerTraverseState.maxStackSize = 0;
#endif
numObjectVisited = 0;
timesAnyObjectVisited = 0;
@@ -1943,13 +1952,13 @@ retainerProfile(void)
and this operation is not costly anyhow). However, we just refresh the
retainer sets.
*/
- initializeTraverseStack();
+ initializeTraverseStack(&g_retainerTraverseState);
#if defined(DEBUG_RETAINER)
initializeAllRetainerSet();
#else
refreshAllRetainerSet();
#endif
- computeRetainerSet();
+ computeRetainerSet(&g_retainerTraverseState);
#if defined(DEBUG_RETAINER)
debugBelch("After traversing:\n");
@@ -1991,7 +2000,7 @@ retainerProfile(void)
#endif
// post-processing
- closeTraverseStack();
+ closeTraverseStack(&g_retainerTraverseState);
#if defined(DEBUG_RETAINER)
closeAllRetainerSet();
#else
@@ -2002,7 +2011,7 @@ retainerProfile(void)
stat_endRP(
retainerGeneration - 1, // retainerGeneration has just been incremented!
#if defined(DEBUG_RETAINER)
- maxStackSize,
+ g_retainerTraverseState.maxStackSize,
#endif
(double)timesAnyObjectVisited / numObjectVisited);
}