@define dumpcode(hp) { @local p, mf, ml, n, nl, tab; p = hp->alloc; n = 0; nl = 0; ml = 0; mf = 0; tab = [ "code" : 0, "labels" : 0, "insn" : 0, "expr" : 0, ]; while(p){ // if(p->color == dom`GCfree) if(((p->bits>>5)&7) == 3) mf += esize(p); else{ ml += szcode((`Code*)p, tab); nl++; } p = p->alink; n++; } printf("%d code objects (%d live)\n", n, nl); printf("%d live code bytes\n", ml); printf("%d free code bytes\n", mf); dumptab("%10s = %10d bytes\n", tab); } @define szcode(cp, tab) { @local m, x, dom, p; m = 0; x = esize(cp); tab["code"] += x; m += x; // FIXME: constant pool? x = 0; p = cp->clist; dom = domof(p); while(p){ if(p->ckind == dom`Clabel) x += esize(p->label); x += esize(p); p = p->link; } x += esize(cp->labels); tab["labels"] += x; m += x; x = esize(cp->insn); tab["insn"] += x; m += x; x = szexpr(cp->src); tab["expr"] += x; m += x; return m; } @define szexpr(e) { @local m, dom; if(e == 0) return 0; dom = domof(e); m = 0; m += esize(e); if(e->kind == dom`Eelist){ while(e->kind == dom`Eelist){ m += szexpr(e->e1); e = e->e2; m += esize(e); } return m; } switch(e->kind){ case dom`Eid: // m += esize(e->id); break; case dom`Econsts: // m += esize(e->lits); break; default: break; } m += szexpr(e->e1); m += szexpr(e->e2); m += szexpr(e->e3); m += szexpr(e->e4); if(e->xp) m += szexprx(e); return m; } @define szexprx(e) { @local m, dom, v; m = 0; dom = domof(e); switch(e->kind){ case dom`Eid: v = (`Var*)e->xp; if(v->where == dom`Vtop) /* other wheres point to lambda/block vars */ m += esize(v); break; case dom`Elambda: m += szlambda((`Lambda*)e->xp); break; case dom`Eblock: m += szblock((`Block*)e->xp); break; case dom`Etypedef: case dom`Edecl: case dom`Edecls: m += szdecl((`Decl*)e->xp); break; default: break; } return m; } @define szlambda(l) { @local m; m = 0; m += esize(l->cap); m += esize(l->disp); m += esize(l->param); m += esize(l); return m; } @define szblock(b) { @local m; m = 0; m += esize(b->loc); m += esize(b); return m; } @define szdecl(d) { @local m; m = 0; while(d){ m += sztype(d->type); m += szexpr(d->attr); m += esize(d->id); m += esize(d); d = d->link; } return m; } @define sztype(t) { @local m; if(t == 0) return 0; m = 0; m += sztype(t->link); m += esize(t->dom); m += esize(t->tid); m += esize(t->tag); m += szdecl(t->field); m += szenum(t->en); m += szdecl(t->param); m += szexpr(t->bitw); m += szexpr(t->sz); m += szexpr(t->cnt); m += esize(t); return m; } @define szenum(en) { @local m, dom; m = 0; dom = domof(en); if(en == (`Enum*)dom`EmptyDecl) return 0; while(en){ m += szexpr(en->val); m += esize(en); en = en->link; } return m; } @define hforeach(ht, fn) { @local i, hp; for(i = 0; i < ht->sz; i++){ hp = ht->ht[i]; while(hp){ fn(hp->key, hp->val); hp = hp->next; } } } @define hsz(ht) { @local m, i, hp; m = 0; m += esize(ht); m += esize(ht->ht); m += esize(ht->hent); for(i = 0; i < ht->sz; i++){ hp = ht->ht[i]; while(hp){ m += esize(hp); hp = hp->next; } } return m; } @define esize(p) { @local dom, x; dom = domof(p); if(p == 0) return 0; p = (void*)p; p -= sizeof(dom`size_t); p = (`size_t*)p; x = *p; return sizeof(dom`size_t)+x; } @define time(fn) { @local s, e; s = gettimeofday(); fn(); e = gettimeofday(); printf("%d seconds %d useconds\n", (e-s)/1000000, (e-s)%1000000); } @define codestat(dom) { @local hp; hp = &dom`heap[dom`Qcode]; time(@lambda(){dumpcode(hp);}); }