Commit c7def600 authored by Daniel Gröber (dxld)'s avatar Daniel Gröber (dxld)

rts: retainer: Move mut_list reset to generic traversal code

parent f9b4c4f2
...@@ -98,9 +98,9 @@ static uint32_t timesAnyObjectVisited; // number of times any objects are ...@@ -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?" * the global 'flip' variable. We interpret this as resetting all the "visited?"
* flags on the heap. * flags on the heap.
* *
* There is one exception to this rule, namely: static objects. There we do just * There are some complications with this approach, namely: static objects and
* go over the heap and reset the bit manually. See * mutable data. There we do just go over all existing objects to reset the bit
* 'resetStaticObjectForProfiling'. * manually. See 'resetStaticObjectForProfiling' and 'resetMutableObjects'.
*/ */
StgWord flip = 0; // flip bit StgWord flip = 0; // flip bit
// must be 0 if DEBUG_RETAINER is on (for static closures) // 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 ...@@ -1410,6 +1410,33 @@ retainVisitClosure( const StgClosure *c, const StgClosure *cp, const stackData d
return 0; 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' * Traverse all closures on the traversal work-stack, calling 'visit_cb'
* on each closure. See 'visitClosure_cb' for details. * on each closure. See 'visitClosure_cb' for details.
...@@ -1435,6 +1462,7 @@ loop: ...@@ -1435,6 +1462,7 @@ loop:
if (c == NULL) { if (c == NULL) {
debug("maxStackSize= %d\n", ts->maxStackSize); debug("maxStackSize= %d\n", ts->maxStackSize);
resetMutableObjects();
return; return;
} }
inner_loop: inner_loop:
...@@ -1592,22 +1620,7 @@ inner_loop: ...@@ -1592,22 +1620,7 @@ inner_loop:
} }
/** /**
* Compute the retainer set for every object reachable from *tl. * Push every object reachable from *tl onto the traversal work stack.
*
* 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).
*/ */
static void static void
retainRoot(void *user, StgClosure **tl) retainRoot(void *user, StgClosure **tl)
...@@ -1625,7 +1638,6 @@ retainRoot(void *user, StgClosure **tl) ...@@ -1625,7 +1638,6 @@ retainRoot(void *user, StgClosure **tl)
} else { } else {
traversePushClosure(ts, c, c, (stackData)CCS_SYSTEM); traversePushClosure(ts, c, c, (stackData)CCS_SYSTEM);
} }
traverseWorkStack(ts, &retainVisitClosure);
// NOT TRUE: ASSERT(isMember(getRetainerFrom(*tl), retainerSetOf(*tl))); // NOT TRUE: ASSERT(isMember(getRetainerFrom(*tl), retainerSetOf(*tl)));
// *tl might be a TSO which is ThreadComplete, in which // *tl might be a TSO which is ThreadComplete, in which
...@@ -1668,26 +1680,7 @@ computeRetainerSet( traverseState *ts ) ...@@ -1668,26 +1680,7 @@ computeRetainerSet( traverseState *ts )
// Remember old stable name addresses. // Remember old stable name addresses.
rememberOldStableNameAddresses (); rememberOldStableNameAddresses ();
traverseWorkStack(ts, &retainVisitClosure);
// 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);
}
}
}
}
} }
/* ----------------------------------------------------------------------------- /* -----------------------------------------------------------------------------
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment