XXX: trace dump infrastructure
authorBen Gamari <ben@smart-cactus.org>
Thu, 9 May 2019 21:21:12 +0000 (17:21 -0400)
committerBen Gamari <ben@smart-cactus.org>
Tue, 21 May 2019 13:39:37 +0000 (09:39 -0400)
rts/sm/Evac.c
rts/sm/GC.c
rts/sm/Scav.c
rts/sm/TraceDump.c [new file with mode: 0644]
rts/sm/TraceDump.h [new file with mode: 0644]

index 4516478..d5e5082 100644 (file)
@@ -15,6 +15,7 @@
 #include "Rts.h"
 
 #include "Evac.h"
+#include "TraceDump.h"
 #include "Storage.h"
 #include "GC.h"
 #include "GCThread.h"
@@ -557,6 +558,7 @@ loop:
   /* The tag and the pointer are split, to be merged after evacing */
   tag = GET_CLOSURE_TAG(q);
   q = UNTAG_CLOSURE(q);
+  trace_dump_edge(q);
 
   ASSERTM(LOOKS_LIKE_CLOSURE_PTR(q), "invalid closure, info=%p", q->header.info);
 
@@ -954,6 +956,7 @@ evacuate_BLACKHOLE(StgClosure **p)
     StgClosure *q;
     const StgInfoTable *info;
     q = *p;
+    trace_dump_edge(q);
 
     // closure is required to be a heap-allocated BLACKHOLE
     ASSERT(HEAP_ALLOCED_GC(q));
index 2673821..d32aba3 100644 (file)
@@ -15,6 +15,7 @@
 #include "Rts.h"
 #include "HsFFI.h"
 
+#include "TraceDump.h"
 #include "GC.h"
 #include "GCThread.h"
 #include "GCTDecl.h"            // NB. before RtsSignals.h which
@@ -267,6 +268,8 @@ GarbageCollect (uint32_t collect_gen,
    */
   N = collect_gen;
   major_gc = (N == RtsFlags.GcFlags.generations-1);
+  if (major_gc)
+      trace_dump_start_gc();
 
 #if defined(THREADED_RTS)
   if (major_gc && RtsFlags.GcFlags.useNonmoving && concurrent_coll_running) {
@@ -958,6 +961,8 @@ GarbageCollect (uint32_t collect_gen,
   }
 #endif
 
+  trace_dump_end_gc();
+
   RELEASE_SM_LOCK;
 
   SET_GCT(saved_gct);
index e066897..ecd726e 100644 (file)
@@ -45,6 +45,7 @@
 #include "PosixSource.h"
 #include "Rts.h"
 
+#include "TraceDump.h"
 #include "Storage.h"
 #include "GC.h"
 #include "GCThread.h"
@@ -101,6 +102,7 @@ scavengeTSO (StgTSO *tso)
     bool saved_eager;
 
     debugTrace(DEBUG_gc,"scavenging thread %d",(int)tso->id);
+    trace_dump_set_source_closure((StgClosure *) tso);
 
     // update the pointer from the InCall.
     if (tso->bound != NULL) {
@@ -446,6 +448,7 @@ scavenge_block (bdescr *bd)
     ASSERT(gct->thunk_selector_depth == 0);
 
     q = p;
+    trace_dump_set_source_closure((StgClosure *) p);
     switch (info->type) {
 
     case MVAR_CLEAN:
@@ -1232,6 +1235,7 @@ scavenge_one(StgPtr p)
 
     ASSERT(LOOKS_LIKE_CLOSURE_PTR(p));
     info = get_itbl((StgClosure *)p);
+    trace_dump_set_source_closure((StgClosure *)p);
 
     switch (info->type) {
 
@@ -1582,6 +1586,7 @@ scavenge_mutable_list(bdescr *bd, generation *gen)
     uint32_t gen_no = gen->no;
     gct->evac_gen_no = gen_no;
 
+    trace_dump_set_source("mut_list");
     for (; bd != NULL; bd = bd->link) {
         for (q = bd->start; q < bd->free; q++) {
             p = (StgPtr)*q;
@@ -1728,6 +1733,7 @@ scavenge_static(void)
 
     ASSERT(LOOKS_LIKE_CLOSURE_PTR(p));
     info = get_itbl(p);
+    trace_dump_set_source_closure((StgClosure *) p);
     // make sure the info pointer is into text space
 
     /* Take this object *off* the static_objects list,
@@ -1818,6 +1824,7 @@ scavenge_stack(StgPtr p, StgPtr stack_end)
   StgWord bitmap;
   StgWord size;
 
+  trace_dump_set_source("STACK");
   /*
    * Each time around this loop, we are looking at a chunk of stack
    * that starts with an activation record.
@@ -2007,6 +2014,7 @@ scavenge_large (gen_workspace *ws)
         }
         RELEASE_SPIN_LOCK(&ws->gen->sync);
 
+        trace_dump_set_source_closure((StgClosure *) p);
         if (scavenge_one(p)) {
             if (ws->gen->no > 0) {
                 recordMutableGen_GC((StgClosure *)p, ws->gen->no);
diff --git a/rts/sm/TraceDump.c b/rts/sm/TraceDump.c
new file mode 100644 (file)
index 0000000..639a6a8
--- /dev/null
@@ -0,0 +1,79 @@
+#include "Rts.h"
+#include "TraceDump.h"
+#include "Trace.h"
+#include "Printer.h"
+
+#if defined(TRACE_DUMP)
+static int gc_n = 0;
+static FILE *trace_dump = NULL;
+static char current_src[255] = "unknown";
+
+void 
+trace_dump_start_gc(void)
+{
+    trace_dump_end_gc();
+
+    char fname[255];
+    snprintf(fname, 255, "trace-dumps/%05d.dot", gc_n);
+    trace_dump = fopen(fname, "w");
+    if (trace_dump == NULL) abort();
+    fprintf(trace_dump, "digraph {\n");
+
+    debugBelch("trace dump: Starting trace %d\n", gc_n);
+    //trace(TRACE_gc, "trace dump: Starting trace %d\n", gc_n);
+    gc_n++;
+}
+
+void 
+trace_dump_end_gc(void)
+{
+    if (trace_dump) {
+        fprintf(trace_dump, "}\n");
+        fclose(trace_dump);
+    }
+    trace_dump = NULL;
+}
+
+void
+trace_dump_set_source(const char *c)
+{
+    strncpy(current_src, c, sizeof(current_src));
+}
+
+void
+trace_dump_set_source_closure(StgClosure *c)
+{
+    c = UNTAG_CLOSURE(c);
+    snprintf(current_src, sizeof(current_src), "%p", c);
+    if (!trace_dump)
+        return;
+
+    const StgInfoTable *info = get_itbl(c);
+    const char *type;
+    switch ( info->type ) {
+    case CONSTR:
+    case CONSTR_1_0: case CONSTR_0_1:
+    case CONSTR_1_1: case CONSTR_0_2: case CONSTR_2_0:
+    case CONSTR_NOCAF:
+    {
+        const StgConInfoTable *con_info = get_con_itbl (c);
+        type = GET_CON_DESC(con_info);
+        break;
+    }
+    default:
+        type = closure_type_names[info->type];
+    }
+
+    fprintf(trace_dump, "  \"%p\" [label=\"%p\\n%s\" info=\"%p\" type=\"%s\"];\n", 
+            UNTAG_CLOSURE(c), UNTAG_CLOSURE(c), type, info, type);
+}
+
+void
+trace_dump_edge(StgClosure *tgt)
+{
+    if (!trace_dump)
+        return;
+    fprintf(trace_dump, "  \"%s\" -> \"%p\";\n", current_src, UNTAG_CLOSURE(tgt));
+}
+
+#endif
diff --git a/rts/sm/TraceDump.h b/rts/sm/TraceDump.h
new file mode 100644 (file)
index 0000000..5d9d8a5
--- /dev/null
@@ -0,0 +1,19 @@
+//#define TRACE_DUMP
+#if defined(TRACE_DUMP)
+
+void trace_dump_start_gc(void);
+void trace_dump_end_gc(void);
+void trace_dump_set_source(const char *c);
+void trace_dump_set_source_closure(StgClosure *c);
+void trace_dump_edge(StgClosure *tgt);
+
+#else
+
+static inline void trace_dump_start_gc(void) {}
+static inline void trace_dump_end_gc(void) {}
+static inline void trace_dump_set_source_closure(StgClosure *c STG_UNUSED) {}
+static inline void trace_dump_set_source(const char *c STG_UNUSED) {}
+static inline void trace_dump_node(StgClosure *c STG_UNUSED) {}
+static inline void trace_dump_edge(StgClosure *tgt STG_UNUSED) {}
+
+#endif