diff options
author | Daniel Gröber <dxld@darkboxed.org> | 2019-07-16 16:05:36 +0200 |
---|---|---|
committer | Daniel Gröber <dxld@darkboxed.org> | 2019-09-22 15:18:10 +0200 |
commit | 96adf1798527e1974a5daa196b50ef2840106c3c (patch) | |
tree | 1fb1ab1ab918e5351397b1dc1242998e6329e575 /rts | |
parent | 9bf27060b1dd919f489a70457052689b5d7a195a (diff) | |
download | haskell-96adf1798527e1974a5daa196b50ef2840106c3c.tar.gz |
rts: retainer: Improve Note [Profiling heap traversal visited bit]
Diffstat (limited to 'rts')
-rw-r--r-- | rts/RetainerProfile.c | 40 |
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 |