diff options
author | Daniel Gröber <dxld@darkboxed.org> | 2019-06-24 18:24:30 +0200 |
---|---|---|
committer | Daniel Gröber <dxld@darkboxed.org> | 2019-09-22 15:18:10 +0200 |
commit | 2b76cf9e163a4fb9400b4ee5c2f8d1b27e94632c (patch) | |
tree | 232379a609ea1711b7cc31d7bcdfd72a38b305b8 | |
parent | bb92660c9d9c226f7ec068dd54d235c5cd4f6d84 (diff) | |
download | haskell-2b76cf9e163a4fb9400b4ee5c2f8d1b27e94632c.tar.gz |
rts: retainer: Move heap traversal declarations to new header
-rw-r--r-- | rts/RetainerProfile.c | 95 | ||||
-rw-r--r-- | rts/RetainerProfile.h | 9 | ||||
-rw-r--r-- | rts/TraverseHeap.h | 120 |
3 files changed, 128 insertions, 96 deletions
diff --git a/rts/RetainerProfile.c b/rts/RetainerProfile.c index c426205f46..9e9f2462ed 100644 --- a/rts/RetainerProfile.c +++ b/rts/RetainerProfile.c @@ -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 diff --git a/rts/RetainerProfile.h b/rts/RetainerProfile.h index 5d54afe2aa..ba0161c98d 100644 --- a/rts/RetainerProfile.h +++ b/rts/RetainerProfile.h @@ -12,24 +12,17 @@ #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 index 0000000000..5a19697694 --- /dev/null +++ b/rts/TraverseHeap.h @@ -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 */ |