diff options
author | Daniel Gröber <dxld@darkboxed.org> | 2019-06-24 21:29:10 +0200 |
---|---|---|
committer | Daniel Gröber <dxld@darkboxed.org> | 2019-09-22 15:18:10 +0200 |
commit | c7def600c24d7f42d43e2bed1b6b3b0ad21d4471 (patch) | |
tree | d2d1fdcab272deed34033380a0410e574d89d3cd /rts | |
parent | f9b4c4f2f66d88c5c962e7f85c4ae675b959551e (diff) | |
download | haskell-c7def600c24d7f42d43e2bed1b6b3b0ad21d4471.tar.gz |
rts: retainer: Move mut_list reset to generic traversal code
Diffstat (limited to 'rts')
-rw-r--r-- | rts/RetainerProfile.c | 73 |
1 files changed, 33 insertions, 40 deletions
diff --git a/rts/RetainerProfile.c b/rts/RetainerProfile.c index 4eec4e98c6..2bb5a503f3 100644 --- a/rts/RetainerProfile.c +++ b/rts/RetainerProfile.c @@ -98,9 +98,9 @@ static uint32_t timesAnyObjectVisited; // number of times any objects are * the global 'flip' variable. We interpret this as resetting all the "visited?" * flags on the heap. * - * There is one exception to this rule, namely: static objects. There we do just - * go over the heap and reset the bit manually. See - * 'resetStaticObjectForProfiling'. + * 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'. */ StgWord flip = 0; // flip bit // must be 0 if DEBUG_RETAINER is on (for static closures) @@ -1410,6 +1410,33 @@ retainVisitClosure( const StgClosure *c, const StgClosure *cp, const stackData d return 0; } +static void +resetMutableObjects(void) +{ + uint32_t g, n; + bdescr *bd; + StgPtr ml; + + // The following code resets the 'trav' field of each unvisited mutable + // object. + for (g = 0; g < RtsFlags.GcFlags.generations; g++) { + // NOT true: even G0 has a block on its mutable list + // ASSERT(g != 0 || (generations[g].mut_list == NULL)); + + // Traversing through mut_list is necessary + // because we can find MUT_VAR objects which have not been + // visited during heap traversal. + for (n = 0; n < n_capabilities; n++) { + for (bd = capabilities[n]->mut_lists[g]; bd != NULL; bd = bd->link) { + for (ml = bd->start; ml < bd->free; ml++) { + + traverseMaybeInitClosureData((StgClosure *)*ml); + } + } + } + } +} + /** * Traverse all closures on the traversal work-stack, calling 'visit_cb' * on each closure. See 'visitClosure_cb' for details. @@ -1435,6 +1462,7 @@ loop: if (c == NULL) { debug("maxStackSize= %d\n", ts->maxStackSize); + resetMutableObjects(); return; } inner_loop: @@ -1592,22 +1620,7 @@ inner_loop: } /** - * Compute the retainer set for every object reachable from *tl. - * - * Compute the retainer set of *c0 and all its desecents by traversing. - * *cp0 is the parent of *c0, and *r0 is the most recent retainer of *c0. - * Invariants: - * c0 = cp0 = r0 holds only for root objects. - * RSET(cp0) and RSET(r0) are valid, i.e., their - * interpretation conforms to the current value of flip (even when they - * are interpreted to be NULL). - * However, RSET(c0) may be corrupt, i.e., it may not conform to - * the current value of flip. If it does not, during the execution - * of this function, RSET(c0) must be initialized as well as all - * its descendants. - * Note: - * stackTop must be the same at the beginning and the exit of this function. - * *c0 can be TSO (as well as AP_STACK). + * Push every object reachable from *tl onto the traversal work stack. */ static void retainRoot(void *user, StgClosure **tl) @@ -1625,7 +1638,6 @@ retainRoot(void *user, StgClosure **tl) } else { traversePushClosure(ts, c, c, (stackData)CCS_SYSTEM); } - traverseWorkStack(ts, &retainVisitClosure); // NOT TRUE: ASSERT(isMember(getRetainerFrom(*tl), retainerSetOf(*tl))); // *tl might be a TSO which is ThreadComplete, in which @@ -1668,26 +1680,7 @@ computeRetainerSet( traverseState *ts ) // Remember old stable name addresses. rememberOldStableNameAddresses (); - - // TODO: Move this code to traverseWorkStack - // The following code resets the rs field of each unvisited mutable - // object. - for (g = 0; g < RtsFlags.GcFlags.generations; g++) { - // NOT true: even G0 has a block on its mutable list - // ASSERT(g != 0 || (generations[g].mut_list == NULL)); - - // Traversing through mut_list is necessary - // because we can find MUT_VAR objects which have not been - // visited during retainer profiling. - for (n = 0; n < n_capabilities; n++) { - for (bd = capabilities[n]->mut_lists[g]; bd != NULL; bd = bd->link) { - for (ml = bd->start; ml < bd->free; ml++) { - - traverseMaybeInitClosureData((StgClosure *)*ml); - } - } - } - } + traverseWorkStack(ts, &retainVisitClosure); } /* ----------------------------------------------------------------------------- |