rts: retainer: Move heap traversal declarations to new header
authorDaniel Gröber <dxld@darkboxed.org>
Mon, 24 Jun 2019 16:24:30 +0000 (18:24 +0200)
committerDaniel Gröber <dxld@darkboxed.org>
Sun, 22 Sep 2019 13:18:10 +0000 (15:18 +0200)
rts/RetainerProfile.c
rts/RetainerProfile.h
rts/TraverseHeap.h [new file with mode: 0644]

index c426205..9e9f246 100644 (file)
@@ -15,6 +15,7 @@
 #include "RtsUtils.h"
 #include "RetainerProfile.h"
 #include "RetainerSet.h"
+#include "TraverseHeap.h"
 #include "Schedule.h"
 #include "Printer.h"
 #include "Weak.h"
@@ -158,13 +159,6 @@ typedef struct {
     nextPos next;
 } stackPos;
 
-typedef union {
-     /**
-      * Most recent retainer for the corresponding closure on the stack.
-      */
-    retainer c_child_r;
-} stackData;
-
 /**
  * An element of the traversal work-stack. Besides the closure itself this also
  * stores it's parent and associated data.
@@ -176,91 +170,16 @@ typedef union {
  * traversePushChildren() and traversePop().
  *
  */
-typedef struct {
+typedef struct stackElement_ {
     stackPos info;
     StgClosure *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
-    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.
- */
-    bdescr *firstStack;
-    bdescr *currentStack;
-    stackElement *stackBottom, *stackTop, *stackLimit;
-
-/*
-  currentStackBoundary is used to mark the current stack chunk.
-  If stackTop == currentStackBoundary, it means that the current stack chunk
-  is empty. It is the responsibility of the user to keep currentStackBoundary
-  valid all the time if it is to be employed.
- */
-    stackElement *currentStackBoundary;
-
-/*
-  stackSize records the current size of the stack.
-  maxStackSize records its high water mark.
-  Invariants:
-    stackSize <= maxStackSize
-  Note:
-    stackSize is just an estimate measure of the depth of the graph. The reason
-    is that some heap objects have only a single child and may not result
-    in a new element being pushed onto the stack. Therefore, at the end of
-    retainer profiling, maxStackSize is some value no greater
-    than the actual depth of the graph.
- */
-    int stackSize, maxStackSize;
-} traverseState;
-
-/**
- * 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
- * this run yet. See Note [Profiling heap traversal visited bit].
- *
- * Return 'true' when this is not the first visit to this element. The generic
- * traversal code will then skip traversing the children.
- */
-typedef bool (*visitClosure_cb) (
-    const StgClosure *c,
-    const StgClosure *cp,
-    const stackData data,
-    stackData *child_data);
-
 traverseState g_retainerTraverseState;
 
 
-static void traverseStack(traverseState *, StgClosure *, stackData, StgPtr, StgPtr);
-static void traverseClosure(traverseState *, StgClosure *, StgClosure *, retainer);
-static void traversePushClosure(traverseState *, StgClosure *, StgClosure *, stackData);
-
 #if defined(DEBUG)
 unsigned int g_traversalDebugLevel = 0;
 static inline void debug(const char *s, ...)
@@ -314,7 +233,7 @@ returnToOldStack( traverseState *ts, bdescr *bd )
 /**
  *  Initializes the traversal work-stack.
  */
-static void
+void
 initializeTraverseStack( traverseState *ts )
 {
     if (ts->firstStack != NULL) {
@@ -334,7 +253,7 @@ initializeTraverseStack( traverseState *ts )
  * Invariants:
  *   firstStack != NULL
  */
-static void
+void
 closeTraverseStack( traverseState *ts )
 {
     freeChain(ts->firstStack);
@@ -494,7 +413,7 @@ pushStackElement(traverseState *ts, stackElement *se)
  *  c    - closure
  *  data - data associated with closure.
  */
-STATIC_INLINE void
+inline void
 traversePushClosure(traverseState *ts, StgClosure *c, StgClosure *cp, stackData data) {
     stackElement se;
 
@@ -1056,7 +975,7 @@ endRetainerProfiling( void )
  *    We have to perform an XOR (^) operation each time a closure is examined.
  *    The reason is that we do not know when a closure is visited last.
  * -------------------------------------------------------------------------- */
-STATIC_INLINE void
+void
 traverseMaybeInitClosureData(StgClosure *c)
 {
     if (!isTravDataValid(c)) {
@@ -1522,7 +1441,7 @@ retainVisitClosure( const StgClosure *c, const StgClosure *cp, const stackData d
  * Traverse all closures on the traversal work-stack, calling 'visit_cb'
  * on each closure. See 'visitClosure_cb' for details.
  */
-static void
+void
 traverseWorkStack(traverseState *ts, visitClosure_cb visit_cb)
 {
     // first_child = first child of c
index 5d54afe..ba0161c 100644 (file)
 #if defined(PROFILING)
 
 #include "RetainerSet.h"
+#include "TraverseHeap.h"
 
 #include "BeginPrivate.h"
 
 void initRetainerProfiling ( void );
 void endRetainerProfiling  ( void );
 void retainerProfile       ( void );
-void resetStaticObjectForProfiling( StgClosure *static_objects );
-
-/* See Note [Profiling heap traversal visited bit]. */
-extern StgWord flip;
 
 // extract the retainer set field from c
 #define RSET(c)   ((c)->header.prof.hp.trav.rs)
 
-
-#define isTravDataValid(c) \
-  ((((StgWord)(c)->header.prof.hp.trav.lsb & 1) ^ flip) == 0)
-
 static inline RetainerSet *
 retainerSetOf( const StgClosure *c )
 {
diff --git a/rts/TraverseHeap.h b/rts/TraverseHeap.h
new file mode 100644 (file)
index 0000000..5a19697
--- /dev/null
@@ -0,0 +1,120 @@
+/* -----------------------------------------------------------------------------
+ *
+ * (c) The GHC Team, 2019
+ * Author: Daniel Gröber
+ *
+ * Generalised profiling heap traversal.
+ *
+ * ---------------------------------------------------------------------------*/
+
+#pragma once
+
+#if defined(PROFILING)
+
+#include <rts/Types.h>
+#include "RetainerSet.h"
+
+#include "BeginPrivate.h"
+
+void resetStaticObjectForProfiling(StgClosure *static_objects);
+
+/* See Note [Profiling heap traversal visited bit]. */
+extern StgWord flip;
+
+#define isTravDataValid(c) \
+  ((((StgWord)(c)->header.prof.hp.trav.lsb & 1) ^ flip) == 0)
+
+typedef struct traverseState_ traverseState;
+
+typedef union stackData_ {
+     /**
+      * Most recent retainer for the corresponding closure on the stack.
+      */
+    retainer c_child_r;
+} stackData;
+
+typedef struct stackElement_ stackElement;
+
+typedef struct traverseState_ {
+/*
+  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
+    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.
+ */
+    bdescr *firstStack;
+    bdescr *currentStack;
+    stackElement *stackBottom, *stackTop, *stackLimit;
+
+/*
+  currentStackBoundary is used to mark the current stack chunk.
+  If stackTop == currentStackBoundary, it means that the current stack chunk
+  is empty. It is the responsibility of the user to keep currentStackBoundary
+  valid all the time if it is to be employed.
+ */
+    stackElement *currentStackBoundary;
+
+/*
+  stackSize records the current size of the stack.
+  maxStackSize records its high water mark.
+  Invariants:
+    stackSize <= maxStackSize
+  Note:
+    stackSize is just an estimate measure of the depth of the graph. The reason
+    is that some heap objects have only a single child and may not result
+    in a new element being pushed onto the stack. Therefore, at the end of
+    retainer profiling, maxStackSize is some value no greater
+    than the actual depth of the graph.
+ */
+    int stackSize, maxStackSize;
+} traverseState;
+
+/**
+ * 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
+ * this run yet. See Note [Profiling heap traversal visited bit].
+ *
+ * Return 'true' when this is not the first visit to this element. The generic
+ * traversal code will then skip traversing the children.
+ */
+typedef bool (*visitClosure_cb) (
+    const StgClosure *c,
+    const StgClosure *cp,
+    const stackData data,
+    stackData *child_data);
+
+void traverseWorkStack(traverseState *ts, visitClosure_cb visit_cb);
+void traversePushClosure(traverseState *ts, StgClosure *c, StgClosure *cp, stackData data);
+void traverseMaybeInitClosureData(StgClosure *c);
+
+void initializeTraverseStack(traverseState *ts);
+void closeTraverseStack(traverseState *ts);
+
+W_ traverseWorkStackBlocks(traverseState *ts);
+
+#include "EndPrivate.h"
+
+#endif /* PROFILING */