diff options
Diffstat (limited to 'rts')
-rw-r--r-- | rts/TraverseHeap.c | 2 | ||||
-rw-r--r-- | rts/TraverseHeap.h | 2 | ||||
-rw-r--r-- | rts/TraverseHeapTest.c | 219 | ||||
-rw-r--r-- | rts/rts.cabal.in | 1 |
4 files changed, 224 insertions, 0 deletions
diff --git a/rts/TraverseHeap.c b/rts/TraverseHeap.c index 8f8b62b2d0..40a70e2a50 100644 --- a/rts/TraverseHeap.c +++ b/rts/TraverseHeap.c @@ -16,6 +16,8 @@ #include "TraverseHeap.h" +const stackData nullStackData; + StgWord getTravData(const StgClosure *c) { const StgWord hp_hdr = c->header.prof.hp.trav; diff --git a/rts/TraverseHeap.h b/rts/TraverseHeap.h index 8ea04dee32..0bc553e094 100644 --- a/rts/TraverseHeap.h +++ b/rts/TraverseHeap.h @@ -69,6 +69,8 @@ typedef union stackData_ { retainer c_child_r; } stackData; +extern const stackData nullStackData; + typedef union stackAccum_ { StgWord subtree_sizeW; } stackAccum; diff --git a/rts/TraverseHeapTest.c b/rts/TraverseHeapTest.c new file mode 100644 index 0000000000..9a71242e55 --- /dev/null +++ b/rts/TraverseHeapTest.c @@ -0,0 +1,219 @@ + +#if defined(PROFILING) && defined(DEBUG) + +#include "PosixSource.h" +#include <string.h> +#include <Rts.h> +#include <rts/storage/Closures.h> +#include "TraverseHeap.h" + +#define container_of(ptr, type, member) ({ \ + const typeof( ((type *)0)->member ) *__mptr = (ptr); \ + (type *)( (char *)__mptr - offsetof(type,member) );}) + +static StgInfoTable info_weak = { .type = WEAK }; +static StgInfoTable info_selector = { .type = THUNK_SELECTOR }; +static StgInfoTable info_arrwords = { .type = ARR_WORDS }; + +struct node { + unsigned int id; + union node_union { + StgClosure cls; + StgWeak weak; + StgSelector selector; + StgArrBytes arrbytes; + } u; +}; + +// See INFO_PTR_TO_STRUCT in ClosureMacros.h +#if defined(TABLES_NEXT_TO_CODE) +#define INFO(ptr) ((StgInfoTable *)ptr + 1) +#else +#define INFO(ptr) ((StgInfoTable *)ptr) +#endif + +#define node3(_id, a,b,c) \ + static struct node n##_id = { \ + .id = _id, \ + .u.weak = { \ + .header = { .info = INFO(&info_weak) }, \ + .key = (StgClosure*)&(n##a.u), \ + .value = (StgClosure*)&(n##b.u), \ + .finalizer = (StgClosure*)&(n##c.u), \ + } \ + }; + +#define node1(_id, a) \ + static struct node n##_id = { \ + .id = _id, \ + .u.selector = { \ + .header = { .info = INFO(&info_selector) }, \ + .selectee = (StgClosure*)&(n##a.u), \ + } \ + } + +#define node0(_id) \ + static struct node n##_id = { \ + .id = _id, \ + .u.arrbytes = { \ + .header = { .info = INFO(&info_arrwords) }, \ + } \ + } + + +/* + 1.0) Just a simple case to start with. + + 1 + / + 0---2 + \ + 3 +*/ +node0(1003); +node0(1002); +node0(1001); +node3(1000, + 1001, + 1002, + 1003); + +/* + 1.1) Now with a cycle + + 1 + /` \, + 0--->2 + \, + 3 +*/ +node0(1103); +node0(1102); +node1(1101, + 1102); +node3(1100, + 1101, + 1102, + 1103); + +/* + 2.0) This tests the chain optimization. + + 1 6 + / / + 0-2-4-5-7 + \ \ + 3 8 +*/ + +node0(2006); +node0(2007); +node0(2008); + +node3(2005, + 2006, + 2007, + 2008); + +node1(2004, + 2005); + +node0(2003); +node1(2002, + 2004); +node0(2001); + +node3(2000, + 2001, + 2002, + 2003); + + +static void +testReturn(StgClosure *c, const stackAccum acc, + StgClosure *c_parent, stackAccum *acc_parent) +{ + (void) acc; + (void) c_parent; + (void) acc_parent; + + struct node *n = container_of(c, struct node, u.cls); + + printf("return %u\n", n->id); + + return; +} + +static bool +testVisit(StgClosure *c, const StgClosure *cp, + const stackData data, const bool first_visit, + stackAccum *acc, stackData *child_data) +{ + (void) cp; + (void) data; + (void) acc; + (void) child_data; + + struct node *n = container_of(c, struct node, u.cls); + + printf("visit %u\n", n->id); + + return first_visit; +} + +static struct node* const g_tests[] = { + &n1000, &n1100, + &n2000, +}; + +static traverseState state; + +void traverseHeapRunTests(void); +void traverseHeapRunTests(void) +{ + traverseState *ts = &state; + + { + printf("with return\n"); + + state.return_cb = &testReturn; + + initializeTraverseStack(ts); + traverseInvalidateClosureData(ts); + + for(size_t i=0; i < (sizeof(g_tests)/sizeof(*g_tests)); i++) { + struct node *n = g_tests[i]; + + stackElement se; + memset(&se, 0, sizeof(se)); + + printf("\n\npush %u\n", n->id); + traversePushClosure(ts, &n->u.cls, &n->u.cls, &se, nullStackData); + traverseWorkStack(ts, &testVisit); + } + + closeTraverseStack(ts); + } + + { + printf("\n\n\n\njust visit\n"); + + state.return_cb = NULL; + + initializeTraverseStack(ts); + traverseInvalidateClosureData(ts); + + for(size_t i=0; i < (sizeof(g_tests)/sizeof(*g_tests)); i++) { + struct node *n = g_tests[i]; + + printf("\n\npush %u\n", n->id); + traversePushClosure(ts, &n->u.cls, &n->u.cls, NULL, nullStackData); + traverseWorkStack(ts, &testVisit); + } + + closeTraverseStack(ts); + + } +} + +#endif diff --git a/rts/rts.cabal.in b/rts/rts.cabal.in index ed727111ca..a1d0ce39a2 100644 --- a/rts/rts.cabal.in +++ b/rts/rts.cabal.in @@ -479,6 +479,7 @@ library TopHandler.c Trace.c TraverseHeap.c + TraverseHeapTest.c WSDeque.c Weak.c eventlog/EventLog.c |