ref: 2183f9eaeca9fb5d57b637c15707e663caf33575
dir: /libinterp/heapaudit.c/
#include "lib9.h"
#include "interp.h"
#include "pool.h"
typedef struct Audit Audit;
struct Audit
{
Type* t;
ulong n;
ulong size;
Audit* hash;
};
Audit* ahash[128];
extern Pool* heapmem;
extern void conslog(char*, ...);
#define conslog print
typedef struct Typed Typed;
typedef struct Ptyped Ptyped;
extern Type Trdchan;
extern Type Twrchan;
struct Typed
{
char* name;
Type* ptr;
} types[] =
{
{"array", &Tarray},
{"byte", &Tbyte},
{"channel", &Tchannel},
{"list", &Tlist},
{"modlink", &Tmodlink},
{"ptr", &Tptr},
{"string", &Tstring},
{"rdchan", &Trdchan},
{"wrchan", &Twrchan},
{"unspec", nil},
0
};
extern Type* TDisplay;
extern Type* TFont;
extern Type* TImage;
extern Type* TScreen;
extern Type* TFD;
extern Type* TFileIO;
extern Type* Tread;
extern Type* Twrite;
extern Type* fakeTkTop;
extern Type* TSigAlg;
extern Type* TCertificate;
extern Type* TSK;
extern Type* TPK;
extern Type* TDigestState;
extern Type* TAuthinfo;
extern Type* TDESstate;
extern Type* TIPint;
struct Ptyped
{
char* name;
Type** ptr;
} ptypes[] =
{
{"Display", &TDisplay},
{"Font", &TFont},
{"Image", &TImage},
{"Screen", &TScreen},
{"SigAlg", &TSigAlg},
{"Certificate", &TCertificate},
{"SK", &TSK},
{"PK", &TPK},
{"DigestState", &TDigestState},
{"Authinfo", &TAuthinfo},
{"DESstate", &TDESstate},
{"IPint", &TIPint},
{"FD", &TFD},
{"FileIO", &TFileIO},
/* {"Fioread", &Tread}, */
/* {"Fiowrite", &Twrite}, */
{"TkTop", &fakeTkTop},
0
};
static Audit **
auditentry(Type *t)
{
Audit **h, *a;
for(h = &ahash[((ulong)t>>2)%nelem(ahash)]; (a = *h) != nil; h = &a->hash)
if(a->t == t)
break;
return h;
}
void
heapaudit(void)
{
Type *t;
Heap *h;
List *l;
Array *r;
Module *m;
int i, ntype, n;
Bhdr *b, *base, *limit;
Audit *a, **hash;
acquire();
b = poolchain(heapmem);
base = b;
limit = B2LIMIT(b);
while(b != nil) {
if(b->magic == MAGIC_A) {
h = B2D(b);
t = h->t;
n = 1;
if(t == &Tlist) {
l = H2D(List*, h);
t = l->t;
} else if(t == &Tarray) {
r = H2D(Array*, h);
t = r->t;
n = r->len;
}
hash = auditentry(t);
if((a = *hash) == nil){
a = malloc(sizeof(Audit));
if(a == nil)
continue;
a->n = 1;
a->t = t;
a->hash = *hash;
*hash = a;
}else
a->n++;
if(t != nil && t != &Tmodlink && t != &Tstring)
a->size += t->size*n;
else
a->size += b->size;
}
b = B2NB(b);
if(b >= limit) {
base = base->clink;
if(base == nil)
break;
b = base;
limit = B2LIMIT(base);
}
}
for(m = modules; m != nil; m = m->link) {
for(i = 0; i < m->ntype; i++)
if((a = *auditentry(m->type[i])) != nil) {
conslog("%8ld %8lud %3d %s\n", a->n, a->size, i, m->path);
a->size = 0;
break;
}
}
for(i = 0; (t = types[i].ptr) != nil; i++)
if((a = *auditentry(t)) != nil){
conslog("%8ld %8lud %s\n", a->n, a->size, types[i].name);
a->size = 0;
break;
}
for(i = 0; ptypes[i].name != nil; i++)
if((a = *auditentry(*ptypes[i].ptr)) != nil){
conslog("%8ld %8lud %s\n", a->n, a->size, ptypes[i].name);
a->size = 0;
break;
}
ntype = 0;
for(i = 0; i < nelem(ahash); i++)
while((a = ahash[i]) != nil){
ahash[i] = a->hash;
if(a->size != 0)
conslog("%8ld %8lud %p\n", a->n, a->size, a->t);
free(a);
ntype++;
}
release();
}