123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230 |
- implement Profile;
- include "sys.m";
- sys: Sys;
- include "draw.m";
- include "bufio.m";
- bufio: Bufio;
- Iobuf: import bufio;
- include "workdir.m";
- workdir: Workdir;
- include "debug.m";
- debug: Debug;
- Sym: import debug;
- include "dis.m";
- dism: Dis;
- include "profile.m";
- # merge common code
- PROF: con "/prof";
- CTL: con "ctl";
- NAME: con "name";
- MPATH: con "path";
- HISTOGRAM: con "histogram";
- inited: int;
- modl: string;
- lasterr: string;
- bspath := array[] of
- {
- ("/dis/", "/appl/cmd/"),
- ("/dis/", "/appl/"),
- };
- error(s: string)
- {
- lasterr = sys->sprint("%s: %r", s);
- }
- error0(s: string)
- {
- lasterr = s;
- }
- cleare()
- {
- lasterr = nil;
- }
- lasterror(): string
- {
- return lasterr;
- }
- init(): int
- {
- cleare();
- sys = load Sys Sys->PATH;
- bufio = load Bufio Bufio->PATH;
- debug = load Debug Debug->PATH;
- if(debug == nil){
- error("cannot load Debug module");
- return -1;
- }
- debug->init();
- (ok, nil) := sys->stat(PROF + "/ctl");
- if (ok == -1) {
- if(sys->bind("#P", PROF, Sys->MREPL|Sys->MCREATE) < 0){
- error(sys->sprint("cannot bind prof device to /prof"));
- return -1;
- }
- }
- inited = 1;
- return 0;
- }
- end(): int
- {
- cleare();
- inited = 0;
- modl = nil;
- if(write(mkpath(PROF, CTL), "end") < 0)
- return -1;
- return 0;
- }
- start(): int
- {
- cleare();
- if(!inited && init() < 0)
- return -1;
- if(write(mkpath(PROF, CTL), "module " + modl) < 0)
- return -1;
- if(write(mkpath(PROF, CTL), "start") < 0)
- return -1;
- return 0;
- }
- cpstart(pid: int): int
- {
- cleare();
- if(!inited && init() < 0)
- return -1;
- if(write(mkpath(PROF, CTL), "module " + modl) < 0)
- return -1;
- if(write(mkpath(PROF, CTL), "startcp " + string pid) < 0)
- return -1;
- return 0;
- }
- memstart(m: int): int
- {
- cleare();
- if(!inited && init() < 0)
- return -1;
- if(modl != nil && write(mkpath(PROF, CTL), "module " + modl) < 0)
- return -1;
- start := "startmp";
- if(m == 0)
- m = MAIN|HEAP|IMAGE;
- if(m&MAIN)
- start += "1";
- if(m&HEAP)
- start += "2";
- if(m&IMAGE)
- start += "3";
- if(write(mkpath(PROF, CTL), start) < 0)
- return -1;
- return 0;
- }
- stop(): int
- {
- cleare();
- if(!inited && init() < 0)
- return -1;
- if(write(mkpath(PROF, CTL), "stop") < 0)
- return -1;
- return 0;
- }
- sample(i: int): int
- {
- cleare();
- if(i <= 0){
- error0(sys->sprint("bad sample rate %d", i));
- return -1;
- }
- if(write(mkpath(PROF, CTL), "interval " + string i) < 0)
- return -1;
- return 0;
- }
- profile(m: string): int
- {
- cleare();
- modl = m + " " + modl;
- return 0;
- }
- stats(): Prof
- {
- mp: Modprof;
- p: Prof;
- mpl: list of Modprof;
- cleare();
- fd := sys->open(PROF, Sys->OREAD);
- if(fd == nil){
- error(sys->sprint("cannot open %s for reading", PROF));
- return (nil, 0, nil);
- }
- total := 0;
- for(;;){
- (nr, d) := sys->dirread(fd);
- if(nr <= 0)
- break;
- for(i := 0; i < nr; i++){
- if(d[i].name == CTL)
- continue;
- dn := mkpath(PROF, d[i].name);
- mp.name = read(mkpath(dn, NAME));
- mp.path = read(mkpath(dn, MPATH));
- fdh := sys->open(mkpath(dn, HISTOGRAM), Sys->OREAD);
- if(fdh == nil)
- continue;
- (mp.srcpath, mp.linetab, mp.funtab, mp.total) = tprofile(fdh, mp.path);
- if((sp := getb(mp.path)) != nil)
- mp.srcpath = sp;
- if(mp.total != 0){
- mpl = mp :: mpl;
- total += mp.total;
- }
- }
- }
- p.mods = mpl;
- p.total = total;
- return p;
- }
- cpstats(rec: int, v: int): Prof
- {
- m: string;
- mp: Modprof;
- p: Prof;
- mpl: list of Modprof;
- cleare();
- fd := sys->open(PROF, Sys->OREAD);
- if(fd == nil){
- error(sys->sprint("cannot open %s for reading", PROF));
- return (nil, 0, nil);
- }
- total := 0;
- for(;;){
- (nr, d) := sys->dirread(fd);
- if(nr <= 0)
- break;
- for(i:=0; i<nr; i++){
- if(d[i].name == CTL)
- continue;
- dn := mkpath(PROF, d[i].name);
- mp.name = read(mkpath(dn, NAME));
- mp.path = read(mkpath(dn, MPATH));
- fdh := sys->open(mkpath(dn, HISTOGRAM), Sys->OREAD);
- if(fdh == nil)
- continue;
- (m, mp.srcpath, mp.rawtab, mp.linetab, mp.rngtab, mp.total, mp.coverage) = cprofile(fdh, mp.path, rec, v);
- if(mp.name == nil)
- mp.name = m;
- if((sp := getb(mp.path)) != nil)
- mp.srcpath = sp;
- if(len mp.rawtab > 0){
- mpl = mp :: mpl;
- total += mp.total;
- }
- }
- }
- p.mods = mpl;
- p.total = total;
- return p;
- }
- cpfstats(v: int): Prof
- {
- mp: Modprof;
- p: Prof;
- mpl: list of Modprof;
- cleare();
- total := 0;
- (nil, l) := sys->tokenize(modl, " ");
- for( ; l != nil; l = tl l){
- s := hd l;
- suf := suff(s);
- if(suf == nil)
- s += ".dis";
- else
- s = repsuff(s, "."+suf, ".dis");
- if(!exists(s) && s[0] != '/' && s[0:2] != "./")
- s = "/dis/"+s;
- mp.path = s;
- (mp.name, mp.srcpath, mp.rawtab, mp.linetab, mp.rngtab, mp.total, mp.coverage) = cprofile(nil, mp.path, 1, v);
- if((sp := getb(mp.path)) != nil)
- mp.srcpath = sp;
- if(len mp.rawtab > 0){
- mpl = mp :: mpl;
- total += mp.total;
- }
- }
- p.mods = mpl;
- p.total = total;
- return p;
- }
- memstats(): Prof
- {
- mp: Modprof;
- p: Prof;
- mpl: list of Modprof;
- cleare();
- fd := sys->open(PROF, Sys->OREAD);
- if(fd == nil){
- error(sys->sprint("cannot open %s for reading", PROF));
- return (nil, 0, nil);
- }
- total := totale := 0;
- for(;;){
- (nr, d) := sys->dirread(fd);
- if(nr <= 0)
- break;
- for(i:=0; i<nr; i++){
- if(d[i].name == CTL)
- continue;
- dn := mkpath(PROF, d[i].name);
- mp.name = read(mkpath(dn, NAME));
- mp.path = read(mkpath(dn, MPATH));
- fdh := sys->open(mkpath(dn, HISTOGRAM), Sys->OREAD);
- if(fdh == nil)
- continue;
- mp.totals = array[1] of int;
- (mp.srcpath, mp.linetab, mp.funtab, mp.total, mp.totals[0]) = mprofile(fdh, mp.path);
- if((sp := getb(mp.path)) != nil)
- mp.srcpath = sp;
- if(mp.total != 0 || mp.totals[0] != 0){
- mpl = mp :: mpl;
- total += mp.total;
- totale += mp.totals[0];
- }
- }
- }
- p.mods = mpl;
- p.total = total;
- p.totals = array[1] of int;
- p.totals[0] = totale;
- return p;
- }
- tprofile(fd: ref Sys->FD, dis: string): (string, array of int, array of Funprof, int)
- {
- sbl := findsbl(dis);
- if(sbl == nil){
- error0(sys->sprint("cannot locate symbol table file for %s", dis));
- return (nil, nil, nil, 0);
- }
- (sym, err) := debug->sym(sbl);
- if(sym == nil){
- error0(sys->sprint("bad symbol table file: %s", err));
- return (nil, nil, nil, 0);
- }
- nlines := 0;
- nl := len sym.src;
- for(i := 0; i < nl; i++){
- if((l := sym.src[i].stop.line) > nlines)
- nlines = l;
- }
- name := sym.src[0].start.file;
- line := array[nlines+1] of int;
- for(i = 0; i <= nlines; i++)
- line[i] = 0;
- nf := len sym.fns;
- fun := array[nf] of Funprof;
- for(i = 0; i < nf; i++){
- fun[i].name = sym.fns[i].name;
- # src seems to be always nil
- # fun[i].file = sym.fns[i].src.start.file;
- # fun[i].line = (sym.fns[i].src.start.line+sym.fns[i].src.stop.line)/2;
- src := sym.pctosrc(sym.fns[i].offset);
- if(src != nil)
- fun[i].line = src.start.line;
- else
- fun[i].line = 0;
- fun[i].count = 0;
- }
- buf := array[32] of byte;
- # pc := 0;
- tot := 0;
- fi := 0;
- # for(i=0; i < nl; i++) sys->print("%d -> %d\n", i, sym.pctosrc(i).start.line);
- while((m := sys->read(fd, buf, len buf)) > 0){
- (nw, lw) := sys->tokenize(string buf[0:m], " ");
- if(nw != 2){
- error0("bad histogram data");
- return (nil, nil, nil, 0);
- }
- pc := int hd lw;
- f := int hd tl lw;
- rpc := pc-1;
- src := sym.pctosrc(rpc);
- if(src == nil)
- continue;
- l1 := src.start.line;
- l2 := src.stop.line;
- if(l1 == 0 || l2 == 0)
- continue;
- if((nl = l2-l1+1) == 1)
- line[l1] += f;
- else{
- q := f/nl;
- r := f-q*nl;
- for(i = l1; i <= l2; i++)
- line[i] += q+(r-->0);
- }
- if(fi < nf){
- if(rpc >= sym.fns[fi].offset && rpc < sym.fns[fi].stoppc)
- fun[fi].count += f;
- else{
- while(fi < nf && rpc >= sym.fns[fi].stoppc)
- fi++;
- # fi++;
- if(fi >= nf && f != 0)
- error0(sys->sprint("bad fn index"));
- if(fi < nf)
- fun[fi].count += f;
- }
- }
- tot += f;
- # sys->print("pc %d count %d l1 %d l2 %d\n", rpc, f, l1, l2);
- }
- return (name, line, fun, tot);
- }
- cprofile(fd: ref Sys->FD, dis: string, rec: int, v: int): (string, string, array of (int, int), array of int, array of ref Range, int, int)
- {
- freq := v&FREQUENCY;
- sbl := findsbl(dis);
- if(sbl == nil){
- error0(sys->sprint("cannot locate symbol table file for %s", dis));
- return (nil, nil, nil, nil, nil, 0, 0);
- }
- (sym, err) := debug->sym(sbl);
- if(sym == nil){
- error0(sys->sprint("bad symbol table file: %s", err));
- return (nil, nil, nil, nil, nil, 0, 0);
- }
- nlines := 0;
- nl := len sym.src;
- for(i := 0; i < nl; i++){
- if((l := sym.src[i].start.line) > nlines)
- nlines = l;
- if((l = sym.src[i].stop.line) > nlines)
- nlines = l;
- }
- name := sym.src[0].start.file;
- line := array[nlines+1] of int;
- for(i = 0; i <= nlines; i++){
- if(freq)
- line[i] = -1;
- else
- line[i] = 0;
- }
- rng := array[nlines+1] of ref Range;
- for(i = 0; i < nl; i++)
- cover(i, -1, sym, line, rng, freq);
- buf := array[32] of byte;
- nr := 0;
- r := array[1024] of (int, int);
- while((m := sys->read(fd, buf, len buf)) > 0){
- (nw, lw) := sys->tokenize(string buf[0:m], " ");
- if(nw != 2){
- error0("bad histogram data");
- return (nil, nil, nil, nil, nil, 0, 0);
- }
- (r, nr) = add(r, nr, int hd lw, int hd tl lw);
- }
- r = clip(r, nr);
- if(rec){
- wt := nr > 0;
- prf := repsuff(sbl, ".sbl", ".prf");
- if(exists(prf)){
- if(stamp(sbl) > stamp(prf)){
- error0(sys->sprint("%s later than %s", sbl, prf));
- return (nil, nil, nil, nil, nil, 0, 0);
- }
- r = mergeprof(r, readprof(prf));
- nr = len r;
- }
- if(wt && writeprof(prf, r) < 0){
- error0(sys->sprint("cannot write profile file %s", prf));
- return (nil, nil, nil, nil, nil, 0, 0);
- }
- }
- tot := 0;
- lpc := 0;
- dise := dist := 0;
- for(i = 0; i < nr; i++){
- (pc, f) := r[i];
- for( ; lpc < pc; lpc++){
- cover(lpc, 0, sym, line, rng, freq);
- dist++;
- }
- cover(pc, f, sym, line, rng, freq);
- dist++;
- if(f != 0)
- dise++;
- tot += f;
- lpc = pc+1;
- }
- for( ; lpc < nl; lpc++){
- cover(lpc, 0, sym, line, rng, freq);
- dist++;
- }
- if(dist == 0)
- dist = 1;
- return (sym.name, name, r, line, rng, tot, (100*dise)/dist);
- }
- show(p: Prof, v: int): int
- {
- i: int;
- cleare();
- tot := p.total;
- if(tot == 0)
- return 0;
- verbose := v&VERBOSE;
- fullhdr := v&FULLHDR;
- for(ml := p.mods; ml != nil; ml = tl ml){
- mp := hd ml;
- if(mp.total == 0)
- continue;
- if((b := getb(mp.path)) == nil)
- continue;
- sys->print("\nModule: %s(%s)\n\n", mp.name, mp.path);
- line := mp.linetab;
- if(v&FUNCTION){
- fun := mp.funtab;
- nf := len fun;
- for(i = 0; i < nf; i++)
- if(verbose || fun[i].count != 0){
- if(fullhdr)
- sys->print("%s:", b);
- sys->print("%d\t%.2f\t%s()\n", fun[i].line, 100.0*(real fun[i].count)/(real tot), fun[i].name);
- }
- sys->print("\n**** module sampling points %d ****\n\n", mp.total);
- if(v&LINE)
- sys->print("\n");
- }
- if(v&LINE){
- bio := bufio->open(b, Bufio->OREAD);
- if(bio == nil){
- error(sys->sprint("cannot open %s for reading", b));
- continue;
- }
- i = 1;
- ll := len line;
- while((s := bio.gets('\n')) != nil){
- f := 0;
- if(i < ll)
- f = line[i];
- if(verbose || f != 0){
- if(fullhdr)
- sys->print("%s:", b);
- sys->print("%d\t%.2f\t%s", i, 100.0*(real f)/(real tot), s);
- }
- i++;
- }
- sys->print("\n**** module sampling points %d ****\n\n", mp.total);
- }
- }
- if(p.mods != nil && tl p.mods != nil)
- sys->print("\n**** total sampling points %d ****\n\n", p.total);
- return 0;
- }
- cpshow(p: Prof, v: int): int
- {
- i: int;
- cleare();
- tot := p.total;
- fullhdr := v&FULLHDR;
- freq := v&FREQUENCY;
- for(ml := p.mods; ml != nil; ml = tl ml){
- mp := hd ml;
- if((b := getb(mp.path)) == nil)
- continue;
- sys->print("\nModule: %s(%s)", mp.name, mp.path);
- sys->print("\t%d%% coverage\n\n", mp.coverage);
- if(mp.coverage == 100 && !freq)
- continue;
- line := mp.linetab;
- rng := mp.rngtab;
- bio := bufio->open(b, Bufio->OREAD);
- if(bio == nil){
- error(sys->sprint("cannot open %s for reading", b));
- continue;
- }
- i = 1;
- ll := len line;
- while((s := bio.gets('\n')) != nil){
- f := 0;
- if(i < ll)
- f = line[i];
- if(fullhdr)
- sys->print("%s:", b);
- sys->print("%d\t", i);
- if(rng != nil && i < ll && (r := rng[i]) != nil && multirng(r)){
- for( ; r != nil; r = r.n){
- sys->print("%s", trans(r.f, freq));
- if(r.n != nil)
- sys->print("|");
- }
- }
- else
- sys->print("%s", trans(f, freq));
- sys->print("\t%s", s);
- i++;
- }
- sys->print("\n**** module dis instructions %d ****\n\n", mp.total);
- }
- if(p.mods != nil && tl p.mods != nil)
- sys->print("\n**** total number dis instructions %d ****\n\n", p.total);
- return 0;
- }
- coverage(p: Prof, v: int): Coverage
- {
- i: int;
- clist: Coverage;
- cleare();
- freq := v&FREQUENCY;
- for(ml := p.mods; ml != nil; ml = tl ml){
- mp := hd ml;
- if((b := getb(mp.path)) == nil)
- continue;
- line := mp.linetab;
- rng := mp.rngtab;
- bio := bufio->open(b, Bufio->OREAD);
- if(bio == nil){
- error(sys->sprint("cannot open %s for reading", b));
- continue;
- }
- i = 1;
- ll := len line;
- llist: list of (list of (int, int, int), string);
- while((s := bio.gets('\n')) != nil){
- f := 0;
- if(i < ll)
- f = line[i];
- rlist: list of (int, int, int);
- if(rng != nil && i < ll && (r := rng[i]) != nil){
- for( ; r != nil; r = r.n){
- if(r.u == ∞)
- r.u = len s - 1;
- if(freq){
- if(r.f > 0)
- rlist = (r.l, r.u, r.f) :: rlist;
- }
- else{
- if(r.f&NEX)
- rlist = (r.l, r.u, (r.f&EXE)==EXE) :: rlist;
- }
- }
- }
- else{
- if(freq){
- if(f > 0)
- rlist = (0, len s - 1, f) :: rlist;
- }
- else{
- if(f&NEX)
- rlist = (0, len s - 1, (f&EXE)==EXE) :: nil;
- }
- }
- llist = (rlist, s) :: llist;
- i++;
- }
- if(freq)
- n := mp.total;
- else
- n = mp.coverage;
- clist = (b, n, rev(llist)) :: clist;
- }
- return clist;
- }
- ∞: con 1<<30;
- DIS: con 1;
- EXE: con 2;
- NEX: con 4;
- cover(pc: int, f: int, sym: ref Debug->Sym, line: array of int, rng: array of ref Range, freq: int)
- {
- v: int;
- src := sym.pctosrc(pc);
- if(src == nil)
- return;
- l1 := src.start.line;
- l2 := src.stop.line;
- if(l1 == 0 || l2 == 0)
- return;
- c1 := src.start.pos;
- c2 := src.stop.pos;
- if(freq){
- v = 0;
- if(f > 0)
- v = f;
- }
- else{
- v = DIS;
- if(f > 0)
- v = EXE;
- else if(f == 0)
- v = NEX;
- }
- for(i := l1; i <= l2; i++){
- r1 := 0;
- r2 := ∞;
- if(i == l1)
- r1 = c1;
- if(i == l2)
- r2 = c2;
- if(rng != nil)
- rng[i] = mrgrng(addrng(rng[i], r1, r2, v, freq));
- if(freq){
- if(v > line[i])
- line[i] = v;
- }
- else
- line[i] |= v;
- # if(i==123) sys->print("%d %d-%d %d %d\n", i, r1, r2, v, pc);
- }
- }
- arng(c1: int, c2: int, f: int, tr: ref Range, lr: ref Range, r: ref Range): ref Range
- {
- nr := ref Range(c1, c2, f, tr);
- if(lr == nil)
- r = nr;
- else
- lr.n = nr;
- return r;
- }
- addrng(r: ref Range, c1: int, c2: int, f: int, freq: int): ref Range
- {
- lr: ref Range;
- if(c1 > c2)
- return r;
- for(tr := r; tr != nil; tr = tr.n){
- r1 := tr.l;
- r2 := tr.u;
- if(c1 < r1){
- if(c2 < r1)
- return arng(c1, c2, f, tr, lr, r);
- else if(c2 <= r2){
- r = addrng(r, c1, r1-1, f, freq);
- return addrng(r, r1, c2, f, freq);
- }
- else{
- r = addrng(r, c1, r1-1, f, freq);
- r = addrng(r, r1, r2, f, freq);
- return addrng(r, r2+1, c2, f, freq);
- }
- }
- else if(c1 <= r2){
- if(c2 <= r2){
- v := tr.f;
- tr.l = c1;
- tr.u = c2;
- if(freq){
- if(f > tr.f)
- tr.f = f;
- }
- else
- tr.f |= f;
- r = addrng(r, r1, c1-1, v, freq);
- return addrng(r, c2+1, r2, v, freq);
- }
- else{
- r = addrng(r, c1, r2, f, freq);
- return addrng(r, r2+1, c2, f, freq);
- }
- }
- lr = tr;
- }
- return arng(c1, c2, f, nil, lr, r);
- }
- mrgrng(r: ref Range): ref Range
- {
- lr: ref Range;
- for(tr := r; tr != nil; tr = tr.n){
- if(lr != nil && lr.u >= tr.l)
- sys->print("ERROR %d %d\n", lr.u, tr.l);
- if(lr != nil && lr.f == tr.f && lr.u+1 == tr.l){
- lr.u = tr.u;
- lr.n = tr.n;
- }
- else
- lr = tr;
- }
- return r;
- }
- multirng(r: ref Range): int
- {
- f := r.f;
- for(tr := r; tr != nil; tr = tr.n)
- if(tr.f != f)
- return 1;
- return 0;
- }
- add(r: array of (int, int), nr: int, pc: int, f: int): (array of (int, int), int)
- {
- l := len r;
- if(nr == l){
- s := array[2*l] of (int, int);
- s[0:] = r[0: nr];
- r = s;
- }
- r[nr++] = (pc, f);
- return (r, nr);
- }
- clip(r: array of (int, int), nr: int): array of (int, int)
- {
- l := len r;
- if(nr < l){
- s := array[nr] of (int, int);
- s[0:] = r[0: nr];
- r = s;
- }
- return r;
- }
- readprof(f: string): array of (int, int)
- {
- b := bufio->open(f, Bufio->OREAD);
- if(b == nil)
- return nil;
- nr := 0;
- r := array[1024] of (int, int);
- while((buf := b.gets('\n')) != nil){
- (nw, lw) := sys->tokenize(buf, " ");
- if(nw != 2){
- error0("bad raw data");
- return nil;
- }
- (r, nr) = add(r, nr, int hd lw, int hd tl lw);
- }
- r = clip(r, nr);
- return r;
- }
- mergeprof(r1, r2: array of (int, int)): array of (int, int)
- {
- nr := 0;
- r := array[1024] of (int, int);
- l1 := len r1;
- l2 := len r2;
- for((i, j) := (0, 0); i < l1 || j < l2; ){
- if(i < l1)
- (pc1, f1) := r1[i];
- else
- pc1 = ∞;
- if(j < l2)
- (pc2, f2) := r2[j];
- else
- pc2 = ∞;
- if(pc1 < pc2){
- (r, nr) = add(r, nr, pc1, f1);
- i++;
- }
- else if(pc1 > pc2){
- (r, nr) = add(r, nr, pc2, f2);
- j++;
- }
- else{
- (r, nr) = add(r, nr, pc1, f1+f2);
- i++;
- j++;
- }
- }
- r = clip(r, nr);
- return r;
- }
- writeprof(f: string, r: array of (int, int)): int
- {
- fd := sys->create(f, Sys->OWRITE, 8r664);
- if(fd == nil)
- return -1;
- l := len r;
- for(i := 0; i < l; i++){
- (pc, fr) := r[i];
- sys->fprint(fd, "%d %d\n", pc, fr);
- }
- return 0;
- }
- trans(f: int, freq: int): string
- {
- if(freq)
- return transf(f);
- else
- return transc(f);
- }
- transf(f: int): string
- {
- if(f < 0)
- return " ";
- return string f;
- }
- transc(f: int): string
- {
- c := "";
- case(f){
- 0 => c = " ";
- DIS|EXE => c = "+";
- DIS|NEX => c = "-";
- DIS|EXE|NEX => c = "?";
- * =>
- error(sys->sprint("bad code %d\n", f));
- }
- return c;
- }
- getb(dis: string): string
- {
- b := findb(dis);
- if(b == nil){
- error0(sys->sprint("cannot locate source file for %s\n", dis));
- return nil;
- }
- if(stamp(b) > stamp(dis)){
- error0(sys->sprint("%s later than %s", b, dis));
- return nil;
- }
- return b;
- }
- mkpath(d: string, f: string): string
- {
- return d+"/"+f;
- }
- suff(s: string): string
- {
- (n, l) := sys->tokenize(s, ".");
- if(n > 1){
- while(tl l != nil)
- l = tl l;
- return hd l;
- }
- return nil;
- }
-
- repsuff(s: string, old: string, new: string): string
- {
- lo := len old;
- ls := len s;
- if(lo <= ls && s[ls-lo:ls] == old)
- return s[0:ls-lo]+new;
- return s;
- }
- read(f: string): string
- {
- if((fd := sys->open(f, Sys->OREAD)) == nil){
- error(sys->sprint("cannot open %s for reading", f));
- return nil;
- }
- buf := array[128] of byte;
- n := sys->read(fd, buf, len buf);
- return string buf[0:n];
- }
- write(f: string, s: string): int
- {
- if((fd := sys->open(f, Sys->OWRITE)) == nil){
- error(sys->sprint("cannot open %s for writing", f));
- return -1;
- }
- b := array of byte s;
- if((n := sys->write(fd, b, len b)) != len b){
- error(sys->sprint("cannot write %s to file %s", s, f));
- return -1;
- }
- return 0;
- }
- exists(f: string): int
- {
- return sys->open(f, Sys->OREAD) != nil;
- }
- stamp(f: string): int
- {
- (ok, d) := sys->stat(f);
- if(ok < 0)
- return 0;
- return d.mtime;
- }
- findb(dis: string): string
- {
- if(dism == nil){
- dism = load Dis Dis->PATH;
- if(dism != nil)
- dism->init();
- }
- if(dism != nil && (b := dism->src(dis)) != nil && exists(b))
- return b;
- return findfile(repsuff(dis, ".dis", ".b"));
- }
- findsbl(dis: string): string
- {
- b := findb(dis);
- if(b != nil){
- sbl := repsuff(b, ".b", ".sbl");
- if(exists(sbl))
- return sbl;
- return findfile(sbl);
- }
- return findfile(repsuff(dis, ".dis", ".sbl"));
- }
- findfile(s: string): string
- {
- if(exists(s))
- return s;
- if(s != nil && s[0] != '/'){
- if(workdir == nil)
- workdir = load Workdir Workdir->PATH;
- if(workdir == nil){
- error("cannot load Workdir module");
- return nil;
- }
- s = workdir->init() + "/" + s;
- }
- (d, f) := split(s, '/');
- (fp, nil) := split(f, '.');
- if(fp != nil)
- fp = fp[0: len fp - 1];
- for(k := 0; k < 2; k++){
- if(k == 0)
- str := s;
- else
- str = d;
- ls := len str;
- for(i := 0; i < len bspath; i++){
- (dis, src) := bspath[i];
- ld := len dis;
- if(ls >= ld && str[:ld] == dis){
- if(k == 0)
- ns := src + str[ld:];
- else
- ns = src + str[ld:] + fp + "/" + f;
- if(exists(ns))
- return ns;
- }
- }
- }
- return nil;
- }
- split(s: string, c: int): (string, string)
- {
- for(i := len s - 1; i >= 0; --i)
- if(s[i] == c)
- break;
- return (s[0:i+1], s[i+1:]);
- }
- rev(llist: list of (list of (int, int, int), string)): list of (list of (int, int, int), string)
- {
- r: list of (list of (int, int, int), string);
- for(l := llist; l != nil; l = tl l)
- r = hd l :: r;
- return r;
- }
- mprofile(fd: ref Sys->FD, dis: string): (string, array of int, array of Funprof, int, int)
- {
- sbl := findsbl(dis);
- if(sbl == nil){
- error0(sys->sprint("cannot locate symbol table file for %s", dis));
- return (nil, nil, nil, 0, 0);
- }
- (sym, err) := debug->sym(sbl);
- if(sym == nil){
- error0(sys->sprint("bad symbol table file: %s", err));
- return (nil, nil, nil, 0, 0);
- }
- nlines := 0;
- nl := len sym.src;
- for(i := 0; i < nl; i++){
- if((l := sym.src[i].stop.line) > nlines)
- nlines = l;
- }
- name := sym.src[0].start.file;
- nl0 := 2*(nlines+1);
- line := array[nl0] of int;
- for(i = 0; i < nl0; i++)
- line[i] = 0;
- nf := len sym.fns;
- fun := array[nf] of Funprof;
- for(i = 0; i < nf; i++){
- fun[i].name = sym.fns[i].name;
- # src seems to be always nil
- # fun[i].file = sym.fns[i].src.start.file;
- # fun[i].line = (sym.fns[i].src.start.line+sym.fns[i].src.stop.line)/2;
- src := sym.pctosrc(sym.fns[i].offset);
- if(src != nil)
- fun[i].line = src.start.line;
- else
- fun[i].line = 0;
- fun[i].count = fun[i].counte = 0;
- }
- buf := array[32] of byte;
- # pc := 0;
- ktot := ktot1 := 0;
- fi := 0;
- # for(i=0; i < nl; i++) sys->print("%d -> %d\n", i, sym.pctosrc(i).start.line);
- while((m := sys->read(fd, buf, len buf)) > 0){
- (nw, lw) := sys->tokenize(string buf[0:m], " ");
- if(nw != 2){
- error0("bad histogram data");
- return (nil, nil, nil, 0, 0);
- }
- pc := int hd lw;
- f := int hd tl lw;
- if(pc == 0){
- ktot = f;
- continue;
- }
- if(pc == 1){
- ktot1 = f;
- continue;
- }
- pc -= 2;
- t := pc&1;
- pc /= 2;
- rpc := pc-1;
- src := sym.pctosrc(rpc);
- if(src == nil)
- continue;
- l1 := src.start.line;
- l2 := src.stop.line;
- if(l1 == 0 || l2 == 0)
- continue;
- if((nl = l2-l1+1) == 1)
- line[2*l1+t] += f;
- else{
- q := f/nl;
- r := f-q*nl;
- for(i = l1; i <= l2; i++)
- line[2*i+t] += q+(r-->0);
- }
- if(fi < nf){
- if(rpc >= sym.fns[fi].offset && rpc < sym.fns[fi].stoppc){
- if(t)
- fun[fi].counte += f;
- else
- fun[fi].count += f;
- }
- else{
- while(fi < nf && rpc >= sym.fns[fi].stoppc)
- fi++;
- # fi++;
- if(fi >= nf && f != 0)
- error0(sys->sprint("bad fn index"));
- if(fi < nf){
- if(t)
- fun[fi].counte += f;
- else
- fun[fi].count += f;
- }
- }
- }
- # sys->print("pc %d count %d l1 %d l2 %d\n", rpc, f, l1, l2);
- }
- return (name, line, fun, ktot, ktot1);
- }
- memshow(p: Prof, v: int): int
- {
- i: int;
- cleare();
- tot := p.total;
- if(p.total == 0 && p.totals[0] == 0)
- return 0;
- verbose := v&VERBOSE;
- fullhdr := v&FULLHDR;
- for(ml := p.mods; ml != nil; ml = tl ml){
- mp := hd ml;
- if(mp.total == 0 && mp.totals[0] == 0)
- continue;
- if((b := getb(mp.path)) == nil)
- continue;
- sys->print("\nModule: %s(%s)\n\n", mp.name, mp.path);
- line := mp.linetab;
- if(v&LINE){
- bio := bufio->open(b, Bufio->OREAD);
- if(bio == nil){
- error(sys->sprint("cannot open %s for reading", b));
- continue;
- }
- i = 1;
- ll := len line/2;
- while((s := bio.gets('\n')) != nil){
- f := g := 0;
- if(i < ll){
- f = line[2*i];
- g = line[2*i+1];
- }
- if(verbose || f != 0 || g != 0){
- if(fullhdr)
- sys->print("%s:", b);
- sys->print("%d\t%d\t%d\t%s", i, f, g, s);
- }
- i++;
- }
- if(v&(FUNCTION|MODULE))
- sys->print("\n");
- }
- if(v&FUNCTION){
- fun := mp.funtab;
- nf := len fun;
- for(i = 0; i < nf; i++)
- if(verbose || fun[i].count != 0 || fun[i].counte != 0){
- if(fullhdr)
- sys->print("%s:", b);
- sys->print("%d\t%d\t%d\t%s()\n", fun[i].line, fun[i].count, fun[i].counte, fun[i].name);
- }
- if(v&MODULE)
- sys->print("\n");
- }
- if(v&MODULE)
- sys->print("Module totals\t%d\t%d\n\n", mp.total, mp.totals[0]);
- }
- if(p.mods != nil && tl p.mods != nil)
- sys->print("Grand totals\t%d\t%d\n\n", p.total, p.totals[0]);
- return 0;
- }
|