rts: retainer: Cleanup comments and strings for traversal extraction
authorDaniel Gröber <dxld@darkboxed.org>
Sun, 23 Jun 2019 14:33:25 +0000 (16:33 +0200)
committerDaniel Gröber <dxld@darkboxed.org>
Sun, 22 Sep 2019 13:18:10 +0000 (15:18 +0200)
A lot of comments and strings are still talking about old names, fix
that.

rts/RetainerProfile.c

index c9b4295..d42de2e 100644 (file)
@@ -158,8 +158,10 @@ typedef union {
     } srt;
 } nextPos;
 
-// Tagged stack element, that keeps information how to process
-// the next element in the traverse stack.
+/**
+ * Position pointer into a closure. Determines what the next element to return
+ * for a stackElement is.
+ */
 typedef struct {
     nextPosType type;
     nextPos next;
@@ -172,29 +174,48 @@ typedef union {
     retainer c_child_r;
 } stackData;
 
-// Element in the traverse stack, keeps the element, information
-// how to continue processing the element, and it's retainer set.
+/**
+ * An element of the traversal work-stack. Besides the closure itself this also
+ * stores it's parent and associated data.
+ *
+ * When 'info.type == posTypeFresh' a 'stackElement' represents just one
+ * closure, namely 'c' and 'cp' being it's parent. Otherwise 'info' specifies an
+ * offset into the children of 'c'. This is to support returning a closure's
+ * children one-by-one without pushing one element per child onto the stack. See
+ * traversePushChildren() and traversePop().
+ *
+ */
 typedef struct {
     stackPos info;
     StgClosure *c;
-    StgClosure *cp; // parent of 'c'
+    StgClosure *cp; // parent of 'c'. Only used when info.type == posTypeFresh.
     stackData data;
 } stackElement;
 
 typedef struct {
 /*
   Invariants:
+
     firstStack points to the first block group.
+
     currentStack points to the block group currently being used.
+
     currentStack->free == stackLimit.
+
     stackTop points to the topmost byte in the stack of currentStack.
+
     Unless the whole stack is empty, stackTop must point to the topmost
     object (or byte) in the whole stack. Thus, it is only when the whole stack
-    is empty that stackTop == stackLimit (not during the execution of push()
-    and pop()).
+    is empty that stackTop == stackLimit (not during the execution of
+    pushStackElement() and popStackElement()).
+
     stackBottom == currentStack->start.
+
     stackLimit == currentStack->start + BLOCK_SIZE_W * currentStack->blocks.
+
+
   Note:
+
     When a current stack becomes empty, stackTop is set to point to
     the topmost element on the previous block group so as to satisfy
     the invariants described above.
@@ -226,7 +247,8 @@ typedef struct {
     int stackSize, maxStackSize;
 } traverseState;
 
-/* Callback called when heap traversal visits a closure.
+/**
+ * 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
@@ -298,9 +320,9 @@ returnToOldStack( traverseState *ts, bdescr *bd )
     bd->free = (StgPtr)ts->stackLimit;
 }
 
-/* -----------------------------------------------------------------------------
- *  Initializes the traversstack.
- * -------------------------------------------------------------------------- */
+/**
+ *  Initializes the traversal work-stack.
+ */
 static void
 initializeTraverseStack( traverseState *ts )
 {
@@ -315,11 +337,12 @@ initializeTraverseStack( traverseState *ts )
     newStackBlock(ts, ts->firstStack);
 }
 
-/* -----------------------------------------------------------------------------
- * Frees all the block groups in the traverse stack.
+/**
+ * Frees all the block groups in the traversal works-stack.
+ *
  * Invariants:
  *   firstStack != NULL
- * -------------------------------------------------------------------------- */
+ */
 static void
 closeTraverseStack( traverseState *ts )
 {
@@ -433,15 +456,17 @@ find_srt( stackPos *info )
     }
 }
 
-/* -----------------------------------------------------------------------------
- * Pushes an element onto traverse stack
- * -------------------------------------------------------------------------- */
+/**
+ * Push a set of closures, represented by a single 'stackElement', onto the
+ * traversal work-stack.
+ */
 static void
 pushStackElement(traverseState *ts, stackElement *se)
 {
     bdescr *nbd;      // Next Block Descriptor
     if (ts->stackTop - 1 < ts->stackBottom) {
-        debug("pop() to the next stack.\n");
+        debug("pushStackElement() to the next stack.\n");
+
         // currentStack->free is updated when the active stack is switched
         // to the next stack.
         ts->currentStack->free = (StgPtr)ts->stackTop;
@@ -471,13 +496,12 @@ pushStackElement(traverseState *ts, stackElement *se)
     debug("stackSize = %d\n", ts->stackSize);
 }
 
-/* Push an object onto traverse stack. This method can be used anytime
- * instead of calling retainClosure(), it exists in order to use an
- * explicit stack instead of direct recursion.
+/**
+ * Push a single closure onto the traversal work-stack.
  *
- *  *cp - object's parent
- *  *c - closure
- *  c_child_r - closure retainer.
+ *  cp   - object's parent
+ *  c    - closure
+ *  data - data associated with closure.
  */
 static INLINE void
 traversePushClosure(traverseState *ts, StgClosure *c, StgClosure *cp, stackData data) {
@@ -491,28 +515,34 @@ traversePushClosure(traverseState *ts, StgClosure *c, StgClosure *cp, stackData
     pushStackElement(ts, &se);
 };
 
-/* -----------------------------------------------------------------------------
- *  push() pushes a stackElement representing the next child of *c
- *  onto the traverse stack. If *c has no child, *first_child is set
- *  to NULL and nothing is pushed onto the stack. If *c has only one
- *  child, *c_child is set to that child and nothing is pushed onto
- *  the stack.  If *c has more than two children, *first_child is set
- *  to the first child and a stackElement representing the second
- *  child is pushed onto the stack.
-
- *  Invariants:
- *     *c_child_r is the most recent retainer of *c's children.
- *     *c is not any of TSO, AP, PAP, AP_STACK, which means that
- *        there cannot be any stack objects.
- *  Note: SRTs are considered to  be children as well.
- * -------------------------------------------------------------------------- */
+/**
+ * traversePushChildren() extracts the first child of 'c' in 'first_child' and
+ * conceptually pushes all remaining children of 'c' onto the traversal stack
+ * while associating 'data' with the pushed elements to be returned upon poping.
+ *
+ * If 'c' has no children, 'first_child' is set to NULL and nothing is pushed
+ * onto the stack.
+ *
+ * If 'c' has only one child, 'first_child' is set to that child and nothing is
+ * pushed onto the stack.
+ *
+ * Invariants:
+ *
+ *  - 'c' is not any of TSO, AP, PAP, AP_STACK, which means that there cannot
+ *       be any stack objects.
+ *
+ * Note: SRTs are considered to be children as well.
+ *
+ * Note: When pushing onto the stack we only really push one 'stackElement'
+ * representing all children onto the stack. See traversePop()
+ */
 static INLINE void
 traversePushChildren(traverseState *ts, StgClosure *c, stackData data, StgClosure **first_child)
 {
     stackElement se;
     bdescr *nbd;      // Next Block Descriptor
 
-    debug("push(): stackTop = 0x%x, currentStackBoundary = 0x%x\n", ts->stackTop, ts->currentStackBoundary);
+    debug("traversePushChildren(): stackTop = 0x%x, currentStackBoundary = 0x%x\n", ts->stackTop, ts->currentStackBoundary);
 
     ASSERT(get_itbl(c)->type != TSO);
     ASSERT(get_itbl(c)->type != AP_STACK);
@@ -523,7 +553,7 @@ traversePushChildren(traverseState *ts, StgClosure *c, stackData data, StgClosur
 
     se.c = c;
     se.data = data;
-    // Note: se.cp ommitted on purpose, only retainPushClosure uses that.
+    // Note: se.cp ommitted on purpose, only traversePushClosure uses that.
 
     // fill in se.info
     switch (get_itbl(c)->type) {
@@ -712,19 +742,14 @@ traversePushChildren(traverseState *ts, StgClosure *c, stackData data, StgClosur
     pushStackElement(ts, &se);
 }
 
-/* -----------------------------------------------------------------------------
- *  popOff() and popOffReal(): Pop a stackElement off the traverse stack.
+/**
+ *  popStackElement(): Remove a depleted stackElement from the top of the
+ *  traversal work-stack.
+ *
  *  Invariants:
  *    stackTop cannot be equal to stackLimit unless the whole stack is
- *    empty, in which case popOff() is not allowed.
- *  Note:
- *    You can think of popOffReal() as a part of popOff() which is
- *    executed at the end of popOff() in necessary. Since popOff() is
- *    likely to be executed quite often while popOffReal() is not, we
- *    separate popOffReal() from popOff(), which is declared as an
- *    INLINE function (for the sake of execution speed).  popOffReal()
- *    is called only within popOff() and nowhere else.
- * -------------------------------------------------------------------------- */
+ *    empty, in which case popStackElement() is not allowed.
+ */
 static void
 popStackElement(traverseState *ts) {
     debug("popStackElement(): stackTop = 0x%x, currentStackBoundary = 0x%x\n", ts->stackTop, ts->currentStackBoundary);
@@ -746,7 +771,7 @@ popStackElement(traverseState *ts) {
 
     bdescr *pbd;    // Previous Block Descriptor
 
-    debug("pop() to the previous stack.\n");
+    debug("popStackElement() to the previous stack.\n");
 
     ASSERT(ts->stackTop + 1 == ts->stackLimit);
     ASSERT(ts->stackBottom == (stackElement *)ts->currentStack->start);
@@ -780,9 +805,10 @@ popStackElement(traverseState *ts) {
     debug("stackSize = %d\n", ts->stackSize);
 }
 
-/* -----------------------------------------------------------------------------
+/**
  *  Finds the next object to be considered for retainer profiling and store
  *  its pointer to *c.
+ *
  *  If the unprocessed object was stored in the stack (posTypeFresh), the
  *  this object is returned as-is. Otherwise Test if the topmost stack
  *  element indicates that more objects are left,
@@ -790,20 +816,23 @@ popStackElement(traverseState *ts) {
  *  set *cp and *data appropriately, both of which are stored in the stack
  *  element.  The topmost stack element then is overwritten so as for it to now
  *  denote the next object.
+ *
  *  If the topmost stack element indicates no more objects are left, pop
  *  off the stack element until either an object can be retrieved or
  *  the current stack chunk becomes empty, indicated by true returned by
  *  isOnBoundary(), in which case *c is set to NULL.
+ *
  *  Note:
+ *
  *    It is okay to call this function even when the current stack chunk
  *    is empty.
- * -------------------------------------------------------------------------- */
+ */
 static INLINE void
 traversePop(traverseState *ts, StgClosure **c, StgClosure **cp, stackData *data)
 {
     stackElement *se;
 
-    debug("pop(): stackTop = 0x%x currentStackBoundary = 0x%x\n", ts->stackTop, ts->currentStackBoundary);
+    debug("traversePop(): stackTop = 0x%x currentStackBoundary = 0x%x\n", ts->stackTop, ts->currentStackBoundary);
 
     // Is this the last internal element? If so instead of modifying the current
     // stackElement in place we actually remove it from the stack.
@@ -816,7 +845,8 @@ traversePop(traverseState *ts, StgClosure **c, StgClosure **cp, stackData *data)
         }
 
         // Note: Below every `break`, where the loop condition is true, must be
-        // accompanied by a popOff() otherwise this is an infinite loop.
+        // accompanied by a popStackElement() otherwise this is an infinite
+        // loop.
         se = ts->stackTop;
 
         // If this is a top-level element, you should pop that out.
@@ -845,7 +875,7 @@ traversePop(traverseState *ts, StgClosure **c, StgClosure **cp, stackData *data)
             if (se->info.next.step == 2) {
                 *c = (StgClosure *)((StgMVar *)se->c)->tail;
                 se->info.next.step++;             // move to the next step
-                // no popOff
+                // no popStackElement
             } else {
                 *c = ((StgMVar *)se->c)->value;
                 last = true;
@@ -857,7 +887,7 @@ traversePop(traverseState *ts, StgClosure **c, StgClosure **cp, stackData *data)
             if (se->info.next.step == 2) {
                 *c = ((StgWeak *)se->c)->value;
                 se->info.next.step++;
-                // no popOff
+                // no popStackElement
             } else {
                 *c = ((StgWeak *)se->c)->finalizer;
                 last = true;
@@ -982,7 +1012,7 @@ traversePop(traverseState *ts, StgClosure **c, StgClosure **cp, stackData *data)
         case IND:
         case INVALID_OBJECT:
         default:
-            barf("Invalid object *c in pop(): %d", get_itbl(se->c)->type);
+            barf("Invalid object *c in traversePop(): %d", get_itbl(se->c)->type);
             return;
         }
     } while (*c == NULL);
@@ -1194,7 +1224,7 @@ associate( StgClosure *c, RetainerSet *s )
 }
 
 /* -----------------------------------------------------------------------------
-   Call retainPushClosure for each of the closures covered by a large bitmap.
+   Call traversePushClosure for each of the closures covered by a large bitmap.
    -------------------------------------------------------------------------- */
 
 static void
@@ -1236,24 +1266,32 @@ traverseSmallBitmap (traverseState *ts, StgPtr p, uint32_t size, StgWord bitmap,
     return p;
 }
 
-/* -----------------------------------------------------------------------------
- *  Process all the objects in the stack chunk from stackStart to stackEnd
- *  with *c and *c_child_r being their parent and their most recent retainer,
- *  respectively. Treat stackOptionalFun as another child of *c if it is
- *  not NULL.
+/**
+ *  traversePushStack(ts, cp, data, stackStart, stackEnd) pushes all the objects
+ *  in the STG stack-chunk from stackStart to stackEnd onto the traversal
+ *  work-stack with 'c' and 'data' being their parent and associated data,
+ *  respectively.
+ *
  *  Invariants:
- *    *c is one of the following: TSO, AP_STACK.
- *    If *c is TSO, c == c_child_r.
+ *
+ *    *cp is one of the following: TSO, AP_STACK.
+ *
+ *    If *cp is TSO, c == c_child_r.
+ *
  *    stackStart < stackEnd.
+ *
  *    RSET(c) and RSET(c_child_r) are valid, i.e., their
  *    interpretation conforms to the current value of flip (even when they
  *    are interpreted to be NULL).
+ *
  *    If *c is TSO, its state is not ThreadComplete,or ThreadKilled,
  *    which means that its stack is ready to process.
+ *
  *  Note:
+ *
  *    This code was almost plagiarzied from GC.c! For each pointer,
- *    retainPushClosure() is invoked instead of evacuate().
- * -------------------------------------------------------------------------- */
+ *    traversePushClosure() is invoked instead of evacuate().
+ */
 static void
 traversePushStack(traverseState *ts, StgClosure *cp, stackData data,
                   StgPtr stackStart, StgPtr stackEnd)
@@ -1265,7 +1303,7 @@ traversePushStack(traverseState *ts, StgClosure *cp, stackData data,
     uint32_t size;
 
     /*
-      Each invocation of retainStack() creates a new virtual
+      Each invocation of traversePushStack() creates a new virtual
       stack. Since all such stacks share a single common stack, we
       record the current currentStackBoundary, which will be restored
       at the exit.
@@ -1273,7 +1311,7 @@ traversePushStack(traverseState *ts, StgClosure *cp, stackData data,
     oldStackBoundary = ts->currentStackBoundary;
     ts->currentStackBoundary = ts->stackTop;
 
-    debug("retainStack() called: oldStackBoundary = 0x%x, currentStackBoundary = 0x%x\n",
+    debug("traversePushStack() called: oldStackBoundary = 0x%x, currentStackBoundary = 0x%x\n",
         oldStackBoundary, ts->currentStackBoundary);
 
     ASSERT(get_itbl(cp)->type == STACK);
@@ -1360,19 +1398,19 @@ traversePushStack(traverseState *ts, StgClosure *cp, stackData data,
         }
 
         default:
-            barf("Invalid object found in retainStack(): %d",
+            barf("Invalid object found in traversePushStack(): %d",
                  (int)(info->i.type));
         }
     }
 
     // restore currentStackBoundary
     ts->currentStackBoundary = oldStackBoundary;
-    debug("retainStack() finished: currentStackBoundary = 0x%x\n",
+    debug("traversePushStack() finished: currentStackBoundary = 0x%x\n",
         ts->currentStackBoundary);
 }
 
 /* ----------------------------------------------------------------------------
- * Call retainPushClosure for each of the children of a PAP/AP
+ * Call traversePushClosure for each of the children of a PAP/AP
  * ------------------------------------------------------------------------- */
 
 static INLINE StgPtr
@@ -1495,22 +1533,10 @@ retainVisitClosure( const StgClosure *c, const StgClosure *cp, const stackData d
     return 0;
 }
 
-/* -----------------------------------------------------------------------------
- *  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).
- * -------------------------------------------------------------------------- */
+/**
+ * Traverse all closures on the traversal work-stack, calling 'visit_cb'
+ * on each closure. See 'visitClosure_cb' for details.
+ */
 static void
 traverseWorkStack(traverseState *ts, visitClosure_cb visit_cb)
 {
@@ -1541,7 +1567,7 @@ inner_loop:
     case TSO:
         if (((StgTSO *)c)->what_next == ThreadComplete ||
             ((StgTSO *)c)->what_next == ThreadKilled) {
-            debug("ThreadComplete or ThreadKilled encountered in retainClosure()\n");
+            debug("ThreadComplete or ThreadKilled encountered in traverseWorkStack()\n");
             goto loop;
         }
         break;
@@ -1673,7 +1699,8 @@ inner_loop:
 
     // If first_child is null, c has no child.
     // If first_child is not null, the top stack element points to the next
-    // object. push() may or may not push a stackElement on the stack.
+    // object. traversePushChildren() may or may not push a stackElement on the
+    // stack.
     if (first_child == NULL)
         goto loop;
 
@@ -1684,9 +1711,24 @@ inner_loop:
     goto 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).
+ */
 static void
 retainRoot(void *user, StgClosure **tl)
 {