summaryrefslogtreecommitdiff
path: root/rts
diff options
context:
space:
mode:
Diffstat (limited to 'rts')
-rw-r--r--rts/RetainerProfile.c27
-rw-r--r--rts/TraverseHeap.h15
2 files changed, 25 insertions, 17 deletions
diff --git a/rts/RetainerProfile.c b/rts/RetainerProfile.c
index 2bb5a503f3..1d2807f468 100644
--- a/rts/RetainerProfile.c
+++ b/rts/RetainerProfile.c
@@ -961,16 +961,18 @@ endRetainerProfiling( void )
/**
* Make sure a closure's profiling data is initialized to zero if it does not
- * conform to the current value of the flip bit.
+ * conform to the current value of the flip bit, returns true in this case.
*
* See Note [Profiling heap traversal visited bit].
*/
-void
+bool
traverseMaybeInitClosureData(StgClosure *c)
{
if (!isTravDataValid(c)) {
setTravDataToZero(c);
+ return true;
}
+ return false;
}
/* -----------------------------------------------------------------------------
@@ -1333,7 +1335,7 @@ traversePAP (traverseState *ts,
}
static bool
-retainVisitClosure( const StgClosure *c, const StgClosure *cp, const stackData data, stackData *out_data )
+retainVisitClosure( const StgClosure *c, const StgClosure *cp, const stackData data, const bool first_visit, stackData *out_data )
{
retainer r = data.c_child_r;
RetainerSet *s, *retainerSetOfc;
@@ -1379,7 +1381,7 @@ retainVisitClosure( const StgClosure *c, const StgClosure *cp, const stackData d
} else {
// This is not the first visit to *c.
if (isMember(r, retainerSetOfc))
- return 1; // no need to process child
+ return 0; // no need to process child
if (s == NULL)
associate(c, addElement(r, retainerSetOfc));
@@ -1398,7 +1400,7 @@ retainVisitClosure( const StgClosure *c, const StgClosure *cp, const stackData d
}
if (isRetainer(c))
- return 1; // no need to process child
+ return 0; // no need to process child
// compute c_child_r
out_data->c_child_r = r;
@@ -1407,7 +1409,7 @@ retainVisitClosure( const StgClosure *c, const StgClosure *cp, const stackData d
// now, RSET() of all of *c, *cp, and *r is valid.
// (c, c_child_r) are available.
- return 0;
+ return 1;
}
static void
@@ -1438,8 +1440,10 @@ resetMutableObjects(void)
}
/**
- * Traverse all closures on the traversal work-stack, calling 'visit_cb'
- * on each closure. See 'visitClosure_cb' for details.
+ * Traverse all closures on the traversal work-stack, calling 'visit_cb' on each
+ * closure. See 'visitClosure_cb' for details. This function flips the 'flip'
+ * bit and hence every closure's profiling data will be reset to zero upon
+ * visiting. See Note [Profiling heap traversal visited bit].
*/
void
traverseWorkStack(traverseState *ts, visitClosure_cb visit_cb)
@@ -1536,9 +1540,10 @@ inner_loop:
}
// If this is the first visit to c, initialize its data.
- traverseMaybeInitClosureData(c);
-
- if(visit_cb(c, cp, data, (stackData*)&child_data))
+ bool first_visit = traverseMaybeInitClosureData(c);
+ bool traverse_children
+ = visit_cb(c, cp, data, first_visit, (stackData*)&child_data);
+ if(!traverse_children)
goto loop;
// process child
diff --git a/rts/TraverseHeap.h b/rts/TraverseHeap.h
index 95c6cfbcdf..a82bf0ec6d 100644
--- a/rts/TraverseHeap.h
+++ b/rts/TraverseHeap.h
@@ -85,22 +85,25 @@ typedef struct traverseState_ {
/**
* Callback called when heap traversal visits a closure.
*
- * Before this callback is called the profiling header of the visited closure
- * 'c' is zero'd with 'setTravDataToZero' if this closure hasn't been visited in
- * this run yet. See Note [Profiling heap traversal visited bit].
+ * The callback can assume that the closure's profiling data has been
+ * initialized to zero if this is the first visit during a pass.
*
- * Return 'true' when this is not the first visit to this element. The generic
- * traversal code will then skip traversing the children.
+ * See Note [Profiling heap traversal visited bit].
+ *
+ * Returning 'false' will instruct the heap traversal code to skip processing
+ * this closure's children. If you don't need to traverse any closure more than
+ * once you can simply return 'first_visit'.
*/
typedef bool (*visitClosure_cb) (
const StgClosure *c,
const StgClosure *cp,
const stackData data,
+ const bool first_visit,
stackData *child_data);
void traverseWorkStack(traverseState *ts, visitClosure_cb visit_cb);
void traversePushClosure(traverseState *ts, StgClosure *c, StgClosure *cp, stackData data);
-void traverseMaybeInitClosureData(StgClosure *c);
+bool traverseMaybeInitClosureData(StgClosure *c);
void initializeTraverseStack(traverseState *ts);
void closeTraverseStack(traverseState *ts);