summaryrefslogtreecommitdiff
path: root/rts
diff options
context:
space:
mode:
authorDaniel Gröber <dxld@darkboxed.org>2019-07-16 16:05:36 +0200
committerDaniel Gröber <dxld@darkboxed.org>2019-09-22 15:18:10 +0200
commit96adf1798527e1974a5daa196b50ef2840106c3c (patch)
tree1fb1ab1ab918e5351397b1dc1242998e6329e575 /rts
parent9bf27060b1dd919f489a70457052689b5d7a195a (diff)
downloadhaskell-96adf1798527e1974a5daa196b50ef2840106c3c.tar.gz
rts: retainer: Improve Note [Profiling heap traversal visited bit]
Diffstat (limited to 'rts')
-rw-r--r--rts/RetainerProfile.c40
1 files changed, 20 insertions, 20 deletions
diff --git a/rts/RetainerProfile.c b/rts/RetainerProfile.c
index 1d2807f468..745aad3f7e 100644
--- a/rts/RetainerProfile.c
+++ b/rts/RetainerProfile.c
@@ -78,32 +78,32 @@ static uint32_t timesAnyObjectVisited; // number of times any objects are
* If the RTS is compiled with profiling enabled StgProfHeader can be used by
* profiling code to store per-heap object information.
*
- * When using the generic heap traversal code we use this field to store
- * profiler specific information. However we reserve the LSB of the *entire*
- * 'trav' union (which will overlap with the other fields) for the generic
- * traversal code. We use the bit to decide whether we've already visited this
- * closure in this pass or not. We do this as the heap may contain cyclic
- * references, it being a graph and all, so we would likely just infinite loop
- * if we didn't.
+ * The generic heap traversal code reserves the least significant bit of the
+ * largest members of the 'trav' union to decide whether we've already visited a
+ * given closure in the current pass or not. The rest of the field is free to be
+ * used by the calling profiler.
*
- * We assume that at least the LSB of the largest field in the corresponding
- * union is insignificant. This is true at least for the word aligned pointers
- * which the retainer profiler currently stores there and should be maintained
- * by new users of the 'trav' union.
+ * By doing things this way we implicitly assume that the LSB of the largest
+ * field in the 'trav' union is insignificant. This is true at least for the
+ * word aligned pointers which the retainer profiler currently stores there and
+ * should be maintained by new users of the 'trav' union for example by shifting
+ * the real data up by one bit.
*
- * Now the way the traversal works is that the interpretation of the "visited?"
- * bit depends on the value of the global 'flip' variable. We don't want to have
- * to do another pass over the heap just to reset the bit to zero so instead on
- * each traversal (i.e. each run of the profiling code) we invert the value of
- * the global 'flip' variable. We interpret this as resetting all the "visited?"
- * flags on the heap.
+ * Since we don't want to have to scan the entire heap a second time just to
+ * reset the per-object visitied bit before/after the real traversal we make the
+ * interpretation of this bit dependent on the value of a global variable,
+ * 'flip'.
+ *
+ * When the 'trav' bit is equal to the value of 'flip' the closure data is
+ * valid otherwise not (see isTravDataValid). We then invert the value of 'flip'
+ * on each heap traversal (see traverseWorkStack), in effect marking all
+ * closure's data as invalid at once.
*
* There are some complications with this approach, namely: static objects and
* mutable data. There we do just go over all existing objects to reset the bit
- * manually. See 'resetStaticObjectForProfiling' and 'resetMutableObjects'.
+ * manually. See 'resetStaticObjectForProfiling' and 'computeRetainerSet'.
*/
-StgWord flip = 0; // flip bit
- // must be 0 if DEBUG_RETAINER is on (for static closures)
+StgWord flip = 0;
#define setTravDataToZero(c) \
(c)->header.prof.hp.trav.lsb = flip