lisp-take-1/gc/dotout.c
2024-11-28 18:36:25 -06:00

353 lines
9.6 KiB
C

#ifdef DOTOUT_BUILD
#include <debug.h>
#include <stringtree/new.h>
#include <stringtree/append.h>
#include <stringtree/println.h>
#include <stringtree/free.h>
#include <value/struct.h>
#include <value/prettyprint.h>
#include <value/foreach_accessible_subvalue.h>
#include "struct.h"
#include "dotout.h"
static size_t counter = 0;
static const char* value_kind_to_string[] = {
[vk_uninitalized] = "uninitalized",
[vk_null] = "null",
[vk_builtin_lambda] = "builtin-lambda",
[vk_envrionment] = "environment",
[vk_identifier] = "identifier",
[vk_boolean] = "boolean",
[vk_integer] = "integer",
[vk_list] = "list",
[vk_string] = "string",
[vk_quote] = "quote",
};
void gc_dotout(
const struct gc* this,
const char* label_fmt,
...)
{
ENTER;
char path[PATH_MAX];
sprintf(path, "/tmp/12-%08lu-gc.dot", counter++);
dpvs(path);
FILE* stream = fopen(path, "w");
fprintf(stream, ""
"digraph {" "\n"
"node [" "\n"
"shape = box" "\n"
"fontcolor = black" "\n"
"color = black" "\n"
"fillcolor = white" "\n"
"style = filled" "\n"
"]" "\n"
"edge [" "\n"
"color = white" "\n"
"]" "\n"
"fontcolor = white" "\n"
"bgcolor = \"#331122\"" "\n"
"overlap = false" "\n"
"rankdir = LR" "\n"
"");
// print label:
{
fprintf(stream, "label = \"");
va_list ap;
va_start(ap, label_fmt);
vfprintf(stream, label_fmt, ap);
va_end(ap);
fprintf(stream, "\"" "\n");
}
#if 0
fprintf(stream, ""
"a [" "\n"
"label = \"total_bytes_currently_allocated = %lu\"" "\n"
"]" "\n"
"", this->bytes_currently_allocated);
fprintf(stream, ""
"b [" "\n"
"label = \"last_garbage_collection = %lu\"" "\n"
"]" "\n"
"", this->bytes_of_last_garbage_collection);
fprintf(stream, ""
"internally_referenced_head [ label = \"internally_referenced head\" ]" "\n"
"internally_referenced_tail [ label = \"internally_referenced tail\" ]" "\n"
"");
fprintf(stream, ""
"reaped_head [ label = \"reaped head\" ]" "\n"
"reaped_tail [ label = \"reaped tail\" ]" "\n"
"");
fprintf(stream, ""
"grey_head [ label = \"grey head\" ]" "\n"
"grey_tail [ label = \"grey tail\" ]" "\n"
"");
fprintf(stream, ""
"white_head [ label = \"white head\" ]" "\n"
"white_tail [ label = \"white tail\" ]" "\n"
"");
fprintf(stream, ""
"externally_referenced_head [ label = \"externally_referenced head\" ]" "\n"
"externally_referenced_tail [ label = \"externally_referenced tail\" ]" "\n"
"");
#endif
#if 1
if (this->internally_referenced.head)
{
fprintf(stream, ""
"internally_referenced_head:e -> \"%p\":w [ style = dashed ]" "\n"
"\"%p\":e -> internally_referenced_tail:w [ style = dashed ]" "\n"
"", this->internally_referenced.head, this->internally_referenced.tail);
}
if (this->reaped.head)
{
fprintf(stream, ""
"reaped_head:e -> \"%p\":w [ style = dashed ]" "\n"
"\"%p\":e -> reaped_tail:w [ style = dashed ]" "\n"
"", this->reaped.head, this->reaped.tail);
}
if (this->grey.head)
{
fprintf(stream, ""
"grey_head:e -> \"%p\":w [ style = dashed ]" "\n"
"\"%p\":e -> grey_tail:w [ style = dashed ]" "\n"
"", this->grey.head, this->grey.tail);
}
if (this->white.head)
{
fprintf(stream, ""
"white_head:e -> \"%p\":w [ style = dashed ]" "\n"
"\"%p\":e -> white_tail:w [ style = dashed ]" "\n"
"", this->white.head, this->white.tail);
}
if (this->externally_referenced.head)
{
fprintf(stream, ""
"externally_referenced_head:e -> \"%p\":w [ style = dashed ]" "\n"
"\"%p\":e -> externally_referenced_tail:w [ style = dashed ]" "\n"
"", this->externally_referenced.head, this->externally_referenced.tail);
}
#endif
for (size_t i = 0; i < this->blocks.n; i++)
{
struct block_info info = this->blocks.data[i];
struct value* start = info.start;
for (size_t j = 0, m = info.cap; j < m; j++)
{
struct value* value = &start[j];
const char* kindstring = value_kind_to_string[value->kind];
if (!kindstring)
{
dpvu(value->kind);
TODO;
}
struct stringtree* tree = new_stringtree();
stringtree_append_formatstr(tree, "\"%p\" [", value);
stringtree_append_formatstr(tree, "shape = record" "\n");
if (value->grey.in_set)
{
stringtree_append_formatstr(tree, "fillcolor = grey" "\n");
}
else if (value->white.in_set)
{
stringtree_append_formatstr(tree, "fillcolor = white" "\n");
}
else if (value->reaped.in_set)
{
stringtree_append_formatstr(tree, "fillcolor = purple" "\n");
}
else if (value->externally_referenced.in_set)
{
stringtree_append_formatstr(tree, "fillcolor = green" "\n");
}
else
{
stringtree_append_formatstr(tree, "fillcolor = darkgreen" "\n");
}
stringtree_append_formatstr(tree, "label = \"");
stringtree_append_formatstr(tree, "(%lu, %lu)", i, j);
#if 0
if (value->kind != vk_uninitalized)
{
struct stringtree* pprint = value_prettyprint(value);
stringtree_append_formatstr(tree, "| ");
stringtree_append_stringtree(tree, pprint);
free_stringtree(pprint);
}
#endif
#if 1
stringtree_append_formatstr(tree, "| kind = %s", kindstring);
#endif
if (value->externally_referenced.in_set)
{
stringtree_append_formatstr(tree, "| refcount = %lu",
value->external_refcount);
}
else
{
assert(value->external_refcount == 0);
}
if (value->internally_referenced.in_set)
{
stringtree_append_string_const(tree, "| internally_referenced");
}
if (value->reaped.in_set)
{
stringtree_append_string_const(tree, "| reaped");
}
if (value->white.in_set)
{
stringtree_append_string_const(tree, "| white");
}
if (value->grey.in_set)
{
stringtree_append_string_const(tree, "| grey");
}
if (value->externally_referenced.in_set)
{
stringtree_append_string_const(tree, "| externally_referenced");
}
stringtree_append_formatstr(tree, "\"" "\n");
stringtree_append_formatstr(tree, "]");
stringtree_println(tree, stream);
if (value->kind != vk_uninitalized)
{
value_foreach_accessible_subvalue(value, ({
void callback(struct value* subvalue)
{
fprintf(stream, ""
"\"%p\":e -> \"%p\":w [ style = solid ]" "\n"
"", value, subvalue);
}
callback;
}));
}
#if 1
if (value->internally_referenced.next)
{
fprintf(stream, ""
"\"%p\":e -> \"%p\":w [ style = dashed]" "\n"
"", value, value->internally_referenced.next);
}
if (value->reaped.next)
{
fprintf(stream, ""
"\"%p\":e -> \"%p\":w [ style = dashed ]" "\n"
"", value, value->reaped.next);
}
if (value->grey.next)
{
fprintf(stream, ""
"\"%p\":e -> \"%p\":w [ style = dashed ]" "\n"
"", value, value->grey.next);
}
if (value->white.next)
{
fprintf(stream, ""
"\"%p\":e -> \"%p\":w [ style = dashed ]" "\n"
"", value, value->white.next);
}
if (value->externally_referenced.next)
{
fprintf(stream, ""
"\"%p\":e -> \"%p\":w [ style = dashed ]" "\n"
"", value, value->externally_referenced.next);
}
#endif
free_stringtree(tree);
}
}
fprintf(stream, ""
"}" "\n"
"");
fclose(stream);
EXIT;
}
#endif