📄 bound.c
字号:
#include "gc.h"#include "bound.h"static BB* bbfree;static BBset* bbsfree;static int bballoc;static int bbsalloc;static BB bbz;static BBset bbsz;static BB* firstbb;static BB* lastbb;static BB* wounded;static BB* bbaux;static BBset* recalc;static BBset* bbhash[BBHASH];static BB** ordered;static int bcount;static BBset** heap;static int heapn;static int bsize;static char bbbuff[BBBSIZE];static int bchange;#define bdebug (debug['v'])#define dbg 0#define bcheck 0static longRn(Reg *r){ if(r == R) return -1; return r->rpo;}static BB*bba(void){ BB *b; bballoc++; b = bbfree; if(b == nil) { b = alloc(sizeof(*b)); } else bbfree = b->link; *b = bbz; return b;}static voidbfree(BB *b){ bballoc--; b->link = bbfree; bbfree = b;}static BBset*bbsa(void){ BBset *b; bballoc++; b = bbsfree; if(b == nil) { b = alloc(sizeof(*b)); } else bbsfree = b->link; *b = bbsz; return b;}static voidbsfree(BBset *b){ bballoc--; b->link = bbsfree; bbsfree = b;}static voiddumpheap(void){ int i; for(i = 1; i <= heapn; i++) print(" %d", heap[i]->damage);}static voidcheckheap(void){ int N, N2, n, c; N = heapn; N2 = N >> 1; for(n = 1; n <= N2; n++) { c = n << 1; if((heap[c]->damage > heap[n]->damage) || ((c < N) && (heap[c + 1]->damage > heap[n]->damage))) { print("bad heap (%d:%d) %d [", n, heap[n]->damage, heapn); dumpheap(); print(" ]\n"); abort(); } }}static voiddownheap(int n){ int N, N2, d, c; BBset *s, *t, *u; s = heap[n]; d = s->damage;//print("down %d %d", n, d); N = heapn; N2 = N >> 1; while(n <= N2) { c = n << 1; t = heap[c]; if(c < N) { u = heap[c + 1]; if(t->damage < u->damage) { t = u; c++; } }//print(" [%d %d]", c, t->damage); if(t->damage < d) break; heap[n] = t; t->index = n; n = c; } heap[n] = s; s->index = n;//print("\n");//checkheap();}static voidupheap(int n){ int f, d; BBset *s, *t; s = heap[n]; d = s->damage;//print("up %d %d", n, d); while(n > 1) { f = n >> 1; t = heap[f];//print(" [%d %d]", f, t->damage); if(t->damage >= d) break; heap[n] = t; t->index = n; n = f; } heap[n] = s; s->index = n;//print("\n");//checkheap();}static voidheapremove(BBset *s){ int x; BBset *t; x = s->index; s->index = 0; if(x == 0) return; if(x == heapn) { heapn--; return; } t = heap[heapn--]; heap[x] = t; t->index = x; if(s->damage < t->damage) upheap(x); else downheap(x);}static voidheapadd(BBset *s){ int n; n = heapn + 1; heap[n] = s; s->index = n; heapn = n; upheap(n);}static voidbbsrecalc(BBset *s){ if(s->recalc) return; s->recalc = 1; s->link = recalc; recalc = s; heapremove(s);}static voidbbadd(BB *b, Hval h){ int k; BBset *s; k = h[0] & BBMASK; for(s = bbhash[k]; s != nil; s = s->next) { if(BBEQ(s->hash, h)) { b->set = s; b->link = s->ents; s->ents = b; bbsrecalc(s); return; } } s = bbsa(); s->next = bbhash[k]; bbhash[k] = s; b->set = s; b->link = nil; s->ents = b; BBCP(s->hash, h); bbsrecalc(s);}static inthashbb(BB *b, Hval h){ Reg *r; Prog *p; char *s; int c, f, i, n; r = b->first; s = bbbuff; i = 0; n = BBBSIZE; for(;;) { p = r->prog; if(p->as != ANOP) { if(p->to.type == D_BRANCH) p->to.offset = r->s2->rpo; c = snprint(s, n, "%P", p); s += c; n -= c; i++; } if(r == b->last) break; r = r->link; } if(n == 0) return Bbig; b->len = i; BBMKHASH(bbbuff, BBBSIZE - n, h); f = b->flags; if(i == 1 && r->prog->as == AJMP && b->first->p1 == R) f = Bjo; else if(b->first->p1 != R) f |= Bpre; if(bdebug) print("A %x %s %ux %ux\n", f, bbbuff, h[0], h[1]); return f;}static voidenterbb(BB *b){ Hval h; b->flags = hashbb(b, h); if(b->flags != Bbig) bbadd(b, h);}static voidpreproc(BB *b, int x){ BB *n; Reg *r; ordered[x] = b; if(b->last->rpo - b->first->rpo > BBBIG) { b->flags = Bbig; return; } if(b->first->p2 == nil) { b->flags = Bdel; return; } switch(b->last->prog->as) { case ARET: case AJMP: case AIRETL: break; default: b->flags = Bdel; n = bba(); n->first = b->first; for(r = b->last->link; r != R; r = r->link) { switch(r->prog->as) { case ARET: case AJMP: case AIRETL: n->last = r; n->flags = Bpin; enterbb(n); if(n->flags & Bpin) { n->aux = bbaux; bbaux = n; } else bfree(n); return; } } bfree(n); return; } enterbb(b);}static intp2len(Reg *r){ int c; c = 0; for(r = r->p2; r != nil; r = r->p2link) c++; return c;}static voidcalcdamage(BBset *s){ BB *f; int d, t; s->recalc = 0; f = s->ents; if(f == nil) return; if(f->flags & Bjo) { if(bdebug) print("add %ld jo\n", f->first->rpo); s->damage = COSTJO; heapadd(s); return; } if(f->link == nil) { if(bdebug) print("solo %x %x\n", s->hash[0], s->hash[1]); return; } d = 0; t = 0; while(f != nil) { if((f->flags & (Bpre|Bpin)) == 0 && f->last->link != R) { t = 1; d += (f->last->rpo - f->first->rpo) >> 1; } d += p2len(f->first); f = f->link; } if(t == 0) { if(bdebug) print("all pre %ld\n", s->ents->first->rpo); return; } if(bdebug) print("add %ld %d\n", s->ents->first->rpo, d); if(d > COSTHI) d = COSTHI; s->damage = d; heapadd(s);}static Reg*findjump(BB *b){ Reg *r, *l; r = b->first; l = b->last; for(;;) { if(r->prog->as == AJMP) break; if(r == l) { diag(Z, "findjump botch"); break; } r = r->link; } return r;}static BB*findset(int r){ BB *s, **p; int n, n2; if(r < ordered[0]->first->rpo) return nil; n = bcount; p = ordered; while(n > 0) { n2 = n >> 1; s = p[n2]; if(r < s->first->rpo) { n = n2; continue; } if(r > s->last->rpo) { n2++; p += n2; n -= n2; continue; } return s; } diag(Z, "findset botch"); return nil;}static voidwound(Reg *r){ BB *b, *p, **n; BBset *s; b = findset(r->rpo); if(b == nil) return; s = b->set; if(s == nil) return; for(n = &s->ents; (p = *n) != nil; n = &(*n)->link) { if(p == b) { *n = b->link; b->link = wounded; wounded = b; bbsrecalc(s); return; } }}static voidprintbl(Reg *l){ if(l == nil) { print("Z"); return; } print("%ld", l->rpo); while((l = l->p2link) != nil) print(" %ld", l->rpo);}static voidappset(Reg *e, Reg *s){ for(;;) { if(s->p2link == R) { s->p2link = e; return; } s = s->p2link; }}static Reg*delset(Reg *e, Reg *s){ Reg *c, *l; c = s; l = nil; for(;;) { if(e == c) { if(l == nil) return s->p2link; l->p2link = c->p2link; return s; } l = c; c = c->p2link; if(c == nil) return s; }}static voidredest(Reg *s, Reg *d){ while(s != R) { s->s2 = d; s = s->p2link; }}static voidchangedest(Reg *s, Reg *d, int x){ Reg *l; if(bdebug) { print("change %ld [", s->rpo); printbl(s->p2); print("] -> %ld [", d->rpo); printbl(d->p2); print("]\n"); } if(s->p2 == nil) {// print("deadjmp\n"); return; } l = s->p2; for(;;) { if(bdebug) print("s2 %ld = %ld\n", l->rpo, d->rpo); l->s2 = d; wound(l); if(l->p2link == nil) break; l = l->p2link; } if(x) { l->p2link = delset(s, d->p2); d->p2 = s->p2;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -