diff options
author | Ben Gamari <ben@smart-cactus.org> | 2020-12-09 22:05:54 -0500 |
---|---|---|
committer | Ben Gamari <ben@smart-cactus.org> | 2022-10-14 17:31:59 -0400 |
commit | 42869d450fe101a8322e09f76e2c9ac3f974bc6f (patch) | |
tree | fbaebefd77c8567fc701eeb0770d3eed537c0995 | |
parent | a54827e0b48af33fa9cfde6ad131c6751c2fe321 (diff) | |
download | haskell-42869d450fe101a8322e09f76e2c9ac3f974bc6f.tar.gz |
nonmoving: Mark tracingwip/gc/mark-trace-9.2
-rw-r--r-- | rts/RtsStartup.c | 1 | ||||
-rw-r--r-- | rts/sm/NonMoving.c | 14 | ||||
-rw-r--r-- | rts/sm/NonMovingMark.c | 137 | ||||
-rw-r--r-- | rts/sm/NonMovingMark.h | 6 |
4 files changed, 154 insertions, 4 deletions
diff --git a/rts/RtsStartup.c b/rts/RtsStartup.c index 649489d1e3..180f9a9b68 100644 --- a/rts/RtsStartup.c +++ b/rts/RtsStartup.c @@ -405,6 +405,7 @@ hs_init_ghc(int *argc, char **argv[], RtsConfig rts_config) /* Record initialization times */ stat_endInit(); + mark_trace_start(); } // Compatibility interface diff --git a/rts/sm/NonMoving.c b/rts/sm/NonMoving.c index d47faa2b9f..0a71cc22dc 100644 --- a/rts/sm/NonMoving.c +++ b/rts/sm/NonMoving.c @@ -892,6 +892,7 @@ static void nonmovingPrepareMark(void) // of this. static void nonmovingMarkWeakPtrList(MarkQueue *mark_queue, StgWeak *dead_weak_ptr_list) { + mark_trace_start_root_set("weak-ptr"); for (StgWeak *w = oldest_gen->weak_ptr_list; w; w = w->link) { markQueuePushClosure_(mark_queue, (StgClosure*)w); // Do not mark finalizers and values here, those fields will be marked @@ -915,6 +916,7 @@ static void nonmovingMarkWeakPtrList(MarkQueue *mark_queue, StgWeak *dead_weak_p markQueuePushClosure_(mark_queue, (StgClosure*)w); nonmovingMarkDeadWeak(mark_queue, w); } + mark_trace_end_root_set(); } void nonmovingCollect(StgWeak **dead_weaks, StgTSO **resurrected_threads) @@ -944,19 +946,29 @@ void nonmovingCollect(StgWeak **dead_weaks, StgTSO **resurrected_threads) // Mark roots trace(TRACE_nonmoving_gc, "Marking roots for nonmoving GC"); + mark_trace_start_root_set("CAF"); markCAFs((evac_fn)markQueueAddRoot, mark_queue); + mark_trace_end_root_set(); + mark_trace_start_root_set("cap"); for (unsigned int n = 0; n < n_capabilities; ++n) { markCapability((evac_fn)markQueueAddRoot, mark_queue, capabilities[n], true/*don't mark sparks*/); } + mark_trace_end_root_set(); + mark_trace_start_root_set("sched"); markScheduler((evac_fn)markQueueAddRoot, mark_queue); + mark_trace_end_root_set(); nonmovingMarkWeakPtrList(mark_queue, *dead_weaks); + mark_trace_start_root_set("StablePtr"); markStablePtrTable((evac_fn)markQueueAddRoot, mark_queue); + mark_trace_end_root_set(); // Mark threads resurrected during moving heap scavenging + mark_trace_start_root_set("resurrected"); for (StgTSO *tso = *resurrected_threads; tso != END_TSO_QUEUE; tso = tso->global_link) { markQueuePushClosure_(mark_queue, (StgClosure*)tso); } + mark_trace_end_root_set(); trace(TRACE_nonmoving_gc, "Finished marking roots for nonmoving GC"); // Roots marked, mark threads and weak pointers @@ -1204,6 +1216,8 @@ static void nonmovingMark_(MarkQueue *mark_queue, StgWeak **dead_weaks, StgTSO * current_mark_queue = NULL; freeMarkQueue(mark_queue); stgFree(mark_queue); + mark_trace_end(); + mark_trace_start(); oldest_gen->live_estimate = nonmoving_live_words; oldest_gen->n_old_blocks = 0; diff --git a/rts/sm/NonMovingMark.c b/rts/sm/NonMovingMark.c index 2fd85dc4f0..fc0648c029 100644 --- a/rts/sm/NonMovingMark.c +++ b/rts/sm/NonMovingMark.c @@ -26,6 +26,106 @@ #include "MarkWeak.h" #include "sm/Storage.h" #include "CNF.h" +#include <sys/stat.h> + +static int mark_trace_phase_n = 0; +static int mark_trace_seq_n = 0; +static const StgClosure *mark_trace_from = NULL; +static FILE *mark_trace_file = NULL; +static const char *mark_trace_root_set = NULL; +static const StgClosure mark_trace_root_marker = {}; + +void mark_trace_start() +{ + ASSERT(mark_trace_file == NULL); + char fname[256]; + mkdir("mark-trace", 0755); + debugBelch("===== Starting GC %d\n", mark_trace_phase_n); + snprintf(fname, sizeof(fname), "mark-trace/%d.dot", mark_trace_phase_n); + mark_trace_phase_n++; + mark_trace_seq_n = 0; + mark_trace_file = fopen(fname, "w"); + ASSERT(mark_trace_file); + fprintf(mark_trace_file, "digraph {\n"); +} + +void mark_trace_end() +{ + ASSERT(mark_trace_file); + fprintf(mark_trace_file, "}\n"); + fclose(mark_trace_file); + mark_trace_file = NULL; +} + +void mark_trace_start_root_set(const char* root_set) +{ + ASSERT(mark_trace_file); + fprintf(mark_trace_file, " # start root set: %s\n", root_set); + mark_trace_root_set = root_set; + mark_trace_from = &mark_trace_root_marker; +} + +void mark_trace_end_root_set() +{ + ASSERT(mark_trace_file); + fprintf(mark_trace_file, " # end root set: %s\n", mark_trace_root_set); + mark_trace_root_set = NULL; + mark_trace_from = NULL; +} + +void mark_trace_root(const StgClosure *root) +{ + ASSERT(mark_trace_file); + fprintf(mark_trace_file, " \"%p\" [root];\n", root); +} + +static void mark_trace_set_from(const StgClosure *from) +{ + mark_trace_from = from; + if (from) { + fprintf(mark_trace_file, " \"%p\" [type=%s];\n", + from, closure_type_names[get_itbl(from)->type]); + } +} + +static void mark_trace_edge_(const StgClosure *from, const StgClosure *to, const char *attrs) +{ + ASSERT(mark_trace_file); + fprintf(mark_trace_file, " \"%p\" -> \"%p\" [n=%d %s];\n", + from, to, mark_trace_seq_n, attrs); + if (mark_trace_root_set) { + fprintf(mark_trace_file, " \"%p\" [root_set=\"%s\"];\n", + from, mark_trace_root_set); + } + mark_trace_seq_n++; +} + + +static void mark_trace_edge(const StgClosure *to) +{ + ASSERT(mark_trace_from); + mark_trace_edge_(mark_trace_from, to, ""); +} + +static void mark_trace_srt_edge(const StgClosure *to) +{ + ASSERT(mark_trace_from); + mark_trace_edge_(mark_trace_from, to, "srt=true"); +} + +static void mark_trace_misc_edge(const char *from, const StgClosure *to) +{ + ASSERT(mark_trace_file); + fprintf(mark_trace_file, " %s -> \"%p\" [n=%d];\n", + from, to, mark_trace_seq_n); + mark_trace_seq_n++; +} + +static void mark_trace_upd_rem_set(const StgClosure *to) +{ + mark_trace_set_from(to); + mark_trace_misc_edge("upd_rem_set", to); +} static bool check_in_nonmoving_heap(StgClosure *p); static void mark_closure (MarkQueue *queue, const StgClosure *p, StgClosure **origin); @@ -484,6 +584,7 @@ markQueuePushClosureGC (MarkQueue *q, StgClosure *p) }; q->top->entries[q->top->head] = ent; q->top->head++; + mark_trace_root(p); } static inline @@ -514,6 +615,7 @@ void push_closure (MarkQueue *q, } }; push(q, &ent); + mark_trace_edge(UNTAG_CLOSURE(p)); } static @@ -539,7 +641,9 @@ void push_thunk_srt (MarkQueue *q, const StgInfoTable *info) { const StgThunkInfoTable *thunk_info = itbl_to_thunk_itbl(info); if (thunk_info->i.srt) { - push_closure(q, (StgClosure*)GET_SRT(thunk_info), NULL); + StgClosure *c = (StgClosure*)GET_SRT(thunk_info); + push_closure(q, c, NULL); + mark_trace_srt_edge(c); } } @@ -548,7 +652,9 @@ void push_fun_srt (MarkQueue *q, const StgInfoTable *info) { const StgFunInfoTable *fun_info = itbl_to_fun_itbl(info); if (fun_info->i.srt) { - push_closure(q, (StgClosure*)GET_FUN_SRT(fun_info), NULL); + StgClosure *c = (StgClosure*)GET_FUN_SRT(fun_info); + push_closure(q, c, NULL); + mark_trace_srt_edge(c); } } @@ -602,6 +708,9 @@ void updateRemembSetPushThunkEager(Capability *cap, const StgThunkInfoTable *info, StgThunk *thunk) { + mark_trace_root((StgClosure *) thunk); + mark_trace_set_from((StgClosure *) thunk); + /* N.B. info->i.type mustn't be WHITEHOLE */ MarkQueue *queue = &cap->upd_rem_set.queue; switch (info->i.type) { @@ -650,6 +759,7 @@ void updateRemembSetPushThunkEager(Capability *cap, barf("updateRemembSetPushThunk: invalid thunk pushed: p=%p, type=%d", thunk, info->i.type); } + mark_trace_set_from(NULL); } void updateRemembSetPushThunk_(StgRegTable *reg, StgThunk *p) @@ -661,7 +771,10 @@ inline void updateRemembSetPushClosure(Capability *cap, StgClosure *p) { if (check_in_nonmoving_heap(p)) { MarkQueue *queue = &cap->upd_rem_set.queue; + mark_trace_start_root_set("upd-rem-set"); push_closure(queue, p, NULL); + mark_trace_upd_rem_set(p); + mark_trace_end_root_set(); } } @@ -715,13 +828,17 @@ void updateRemembSetPushTSO(Capability *cap, StgTSO *tso) { if (needs_upd_rem_set_mark((StgClosure *) tso)) { debugTrace(DEBUG_nonmoving_gc, "upd_rem_set: TSO %p", tso); + mark_trace_upd_rem_set((StgClosure *) tso); trace_tso(&cap->upd_rem_set.queue, tso); finish_upd_rem_set_mark((StgClosure *) tso); + mark_trace_set_from(NULL); } } void updateRemembSetPushStack(Capability *cap, StgStack *stack) { + mark_trace_upd_rem_set((StgClosure *) stack); + // N.B. caller responsible for checking nonmoving_write_barrier_enabled if (needs_upd_rem_set_mark((StgClosure *) stack)) { StgWord8 marking = stack->marking; @@ -732,7 +849,6 @@ void updateRemembSetPushStack(Capability *cap, StgStack *stack) debugTrace(DEBUG_nonmoving_gc, "upd_rem_set: STACK %p", stack->sp); trace_stack(&cap->upd_rem_set.queue, stack); finish_upd_rem_set_mark((StgClosure *) stack); - return; } else { // The concurrent GC has claimed the right to mark the stack. // Wait until it finishes marking before proceeding with @@ -743,9 +859,10 @@ void updateRemembSetPushStack(Capability *cap, StgStack *stack) #else ; #endif - return; } } + mark_trace_set_from(NULL); + mark_trace_start_root_set("upd_rem_set"); } /********************************************************* @@ -770,7 +887,9 @@ void markQueuePushClosure (MarkQueue *q, /* TODO: Do we really never want to specify the origin here? */ void markQueueAddRoot (MarkQueue* q, StgClosure** root) { + mark_trace_start_root_set(""); markQueuePushClosure(q, *root, NULL); + mark_trace_end_root_set(); } /* Push a closure to the mark queue without origin information */ @@ -1197,6 +1316,7 @@ mark_closure (MarkQueue *queue, const StgClosure *p0, StgClosure **origin) StgClosure *p_next = NULL; StgWord tag = GET_CLOSURE_TAG(p); p = UNTAG_CLOSURE(p); + mark_trace_set_from(p); # define PUSH_FIELD(obj, field) \ markQueuePushClosure(queue, \ @@ -1687,10 +1807,12 @@ nonmovingMark (MarkQueue *queue) switch (nonmovingMarkQueueEntryType(&ent)) { case MARK_CLOSURE: mark_closure(queue, ent.mark_closure.p, ent.mark_closure.origin); + mark_trace_set_from(NULL); break; case MARK_ARRAY: { const StgMutArrPtrs *arr = (const StgMutArrPtrs *) UNTAG_CLOSURE((StgClosure *) ent.mark_array.array); + mark_trace_set_from((StgClosure*) arr); StgWord start = ent.mark_array.start_index; StgWord end = start + MARK_ARRAY_CHUNK_LENGTH; if (end < arr->ptrs) { @@ -1702,6 +1824,7 @@ nonmovingMark (MarkQueue *queue) for (StgWord i = start; i < end; i++) { markQueuePushClosure_(queue, arr->payload[i]); } + mark_trace_set_from(NULL); break; } case NULL_ENTRY: @@ -1873,9 +1996,13 @@ void nonmovingMarkDeadWeak (struct MarkQueue_ *queue, StgWeak *w) void nonmovingMarkLiveWeak (struct MarkQueue_ *queue, StgWeak *w) { ASSERT(nonmovingClosureMarkedThisCycle((P_)w)); + mark_trace_misc_edge("live-weak", (StgClosure *) w); + mark_trace_edge_(w->key, (StgClosure *) w, "weak-key=true"); + mark_trace_set_from((StgClosure *) w); markQueuePushClosure_(queue, w->value); markQueuePushClosure_(queue, w->finalizer); markQueuePushClosure_(queue, w->cfinalizers); + mark_trace_set_from(NULL); } // When we're done with marking, any weak pointers with non-marked keys will be @@ -1924,6 +2051,7 @@ void nonmovingTidyThreads () // by resurrectThreads. void nonmovingResurrectThreads (struct MarkQueue_ *queue, StgTSO **resurrected_threads) { + mark_trace_start_root_set("resurrected"); StgTSO *next; for (StgTSO *t = nonmoving_old_threads; t != END_TSO_QUEUE; t = next) { next = t->global_link; @@ -1941,6 +2069,7 @@ void nonmovingResurrectThreads (struct MarkQueue_ *queue, StgTSO **resurrected_t *resurrected_threads = t; } } + mark_trace_end_root_set(); } #if defined(DEBUG) diff --git a/rts/sm/NonMovingMark.h b/rts/sm/NonMovingMark.h index 0938e2775a..c0790c3f32 100644 --- a/rts/sm/NonMovingMark.h +++ b/rts/sm/NonMovingMark.h @@ -191,4 +191,10 @@ void printMarkQueue(MarkQueue *q); #endif +void mark_trace_start(void); +void mark_trace_end(void); +void mark_trace_start_root_set(const char* why); +void mark_trace_end_root_set(void); +void mark_trace_root(const StgClosure *root); + #include "EndPrivate.h" |