diff options
| author | Russ Cox <rsc@golang.org> | 2013-08-16 21:45:59 -0400 |
|---|---|---|
| committer | Russ Cox <rsc@golang.org> | 2013-08-16 21:45:59 -0400 |
| commit | 3b4d792606bf6de962bed73e79c261d7ddd7266c (patch) | |
| tree | bb5b0032bf576f09a461fcc0aa6228bc39ec3797 | |
| parent | a96d850a5b17a912c105edfcb358e8319fbea720 (diff) | |
| download | go-3b4d792606bf6de962bed73e79c261d7ddd7266c.tar.xz | |
cmd/gc: separate "has pointers" from "needs zeroing" in stack frame
When the new call site-specific frame bitmaps are available,
we can cut the zeroing to just those values that need it due
to scope escaping.
R=cshapiro, cshapiro
CC=golang-dev
https://golang.org/cl/13045043
| -rw-r--r-- | src/cmd/5g/ggen.c | 10 | ||||
| -rw-r--r-- | src/cmd/6g/ggen.c | 10 | ||||
| -rw-r--r-- | src/cmd/8g/ggen.c | 10 | ||||
| -rw-r--r-- | src/cmd/gc/go.h | 4 | ||||
| -rw-r--r-- | src/cmd/gc/pgen.c | 38 |
5 files changed, 43 insertions, 29 deletions
diff --git a/src/cmd/5g/ggen.c b/src/cmd/5g/ggen.c index 52c2cd4395..f018c88aa8 100644 --- a/src/cmd/5g/ggen.c +++ b/src/cmd/5g/ggen.c @@ -35,11 +35,11 @@ defframe(Prog *ptxt, Bvec *bv) p = ptxt; while(p->link->as == AFUNCDATA || p->link->as == APCDATA || p->link->as == ATYPE) p = p->link; - if(stkptrsize >= 8*widthptr) { + if(stkzerosize >= 8*widthptr) { p = appendp(p, AMOVW, D_CONST, NREG, 0, D_REG, 0, 0); - p = appendp(p, AADD, D_CONST, NREG, 4+frame-stkptrsize, D_REG, 1, 0); + p = appendp(p, AADD, D_CONST, NREG, 4+frame-stkzerosize, D_REG, 1, 0); p->reg = REGSP; - p = appendp(p, AADD, D_CONST, NREG, stkptrsize, D_REG, 2, 0); + p = appendp(p, AADD, D_CONST, NREG, stkzerosize, D_REG, 2, 0); p->reg = 1; p1 = p = appendp(p, AMOVW, D_REG, 0, 0, D_OREG, 1, 4); p->scond |= C_PBIT; @@ -49,13 +49,13 @@ defframe(Prog *ptxt, Bvec *bv) patch(p, p1); } else { first = 1; - for(i=0, j=0; i<stkptrsize; i+=widthptr, j+=2) { + for(i=0, j=(stkptrsize-stkzerosize)/widthptr*2; i<stkzerosize; i+=widthptr, j+=2) { if(bvget(bv, j) || bvget(bv, j+1)) { if(first) { p = appendp(p, AMOVW, D_CONST, NREG, 0, D_REG, 0, 0); first = 0; } - p = appendp(p, AMOVW, D_REG, 0, 0, D_OREG, REGSP, 4+frame-stkptrsize+i); + p = appendp(p, AMOVW, D_REG, 0, 0, D_OREG, REGSP, 4+frame-stkzerosize+i); } } } diff --git a/src/cmd/6g/ggen.c b/src/cmd/6g/ggen.c index ec1d1ddc4c..6e2f0fd69e 100644 --- a/src/cmd/6g/ggen.c +++ b/src/cmd/6g/ggen.c @@ -30,16 +30,16 @@ defframe(Prog *ptxt, Bvec *bv) // so that garbage collector only sees initialized values // when it looks for pointers. p = ptxt; - if(stkptrsize >= 8*widthptr) { + if(stkzerosize >= 8*widthptr) { p = appendp(p, AMOVQ, D_CONST, 0, D_AX, 0); - p = appendp(p, AMOVQ, D_CONST, stkptrsize/widthptr, D_CX, 0); - p = appendp(p, ALEAQ, D_SP+D_INDIR, frame-stkptrsize, D_DI, 0); + p = appendp(p, AMOVQ, D_CONST, stkzerosize/widthptr, D_CX, 0); + p = appendp(p, ALEAQ, D_SP+D_INDIR, frame-stkzerosize, D_DI, 0); p = appendp(p, AREP, D_NONE, 0, D_NONE, 0); appendp(p, ASTOSQ, D_NONE, 0, D_NONE, 0); } else { - for(i=0, j=0; i<stkptrsize; i+=widthptr, j+=2) + for(i=0, j=(stkptrsize-stkzerosize)/widthptr*2; i<stkzerosize; i+=widthptr, j+=2) if(bvget(bv, j) || bvget(bv, j+1)) - p = appendp(p, AMOVQ, D_CONST, 0, D_SP+D_INDIR, frame-stkptrsize+i); + p = appendp(p, AMOVQ, D_CONST, 0, D_SP+D_INDIR, frame-stkzerosize+i); } } diff --git a/src/cmd/8g/ggen.c b/src/cmd/8g/ggen.c index 6b8c67e5bc..1f9e6e0593 100644 --- a/src/cmd/8g/ggen.c +++ b/src/cmd/8g/ggen.c @@ -32,16 +32,16 @@ defframe(Prog *ptxt, Bvec *bv) // so that garbage collector only sees initialized values // when it looks for pointers. p = ptxt; - if(stkptrsize >= 8*widthptr) { + if(stkzerosize >= 8*widthptr) { p = appendp(p, AMOVL, D_CONST, 0, D_AX, 0); - p = appendp(p, AMOVL, D_CONST, stkptrsize/widthptr, D_CX, 0); - p = appendp(p, ALEAL, D_SP+D_INDIR, frame-stkptrsize, D_DI, 0); + p = appendp(p, AMOVL, D_CONST, stkzerosize/widthptr, D_CX, 0); + p = appendp(p, ALEAL, D_SP+D_INDIR, frame-stkzerosize, D_DI, 0); p = appendp(p, AREP, D_NONE, 0, D_NONE, 0); appendp(p, ASTOSL, D_NONE, 0, D_NONE, 0); } else { - for(i=0, j=0; i<stkptrsize; i+=widthptr, j+=2) + for(i=0, j=(stkptrsize-stkzerosize)/widthptr*2; i<stkzerosize; i+=widthptr, j+=2) if(bvget(bv, j) || bvget(bv, j+1)) - p = appendp(p, AMOVL, D_CONST, 0, D_SP+D_INDIR, frame-stkptrsize+i); + p = appendp(p, AMOVL, D_CONST, 0, D_SP+D_INDIR, frame-stkzerosize+i); } } diff --git a/src/cmd/gc/go.h b/src/cmd/gc/go.h index c021e895ef..9232650c28 100644 --- a/src/cmd/gc/go.h +++ b/src/cmd/gc/go.h @@ -270,6 +270,7 @@ struct Node uchar dupok; // duplicate definitions ok (for func) schar likely; // likeliness of if statement uchar hasbreak; // has break statement + uchar needzero; // if it contains pointers, needs to be zeroed on function entry uint esc; // EscXXX int funcdepth; @@ -940,7 +941,8 @@ EXTERN NodeList* lastconst; EXTERN Node* lasttype; EXTERN vlong maxarg; EXTERN vlong stksize; // stack size for current frame -EXTERN vlong stkptrsize; // prefix of stack containing pointers for current frame +EXTERN vlong stkptrsize; // prefix of stack containing pointers +EXTERN vlong stkzerosize; // prefix of stack that must be zeroed on entry EXTERN int32 blockgen; // max block number EXTERN int32 block; // current block number EXTERN int hasdefer; // flag that curfn has defer statetment diff --git a/src/cmd/gc/pgen.c b/src/cmd/gc/pgen.c index edeaa06a69..f391634067 100644 --- a/src/cmd/gc/pgen.c +++ b/src/cmd/gc/pgen.c @@ -367,11 +367,11 @@ dumpgclocals(Node* fn, Sym *sym) // Sort the list of stack variables. Autos after anything else, // within autos, unused after used, within used, things with -// pointers first, and then decreasing size. +// pointers first, zeroed things first, and then decreasing size. // Because autos are laid out in decreasing addresses -// on the stack, pointers first and decreasing size -// really means, in memory, pointers near the top of the -// stack and increasing in size. +// on the stack, pointers first, zeroed things first and decreasing size +// really means, in memory, things with pointers needing zeroing at +// the top of the stack and increasing in size. // Non-autos sort on offset. static int cmpstackvar(Node *a, Node *b) @@ -394,6 +394,12 @@ cmpstackvar(Node *a, Node *b) bp = haspointers(b->type); if(ap != bp) return bp - ap; + + ap = a->needzero; + bp = b->needzero; + if(ap != bp) + return bp - ap; + if(a->type->width < b->type->width) return +1; if(a->type->width > b->type->width) @@ -409,11 +415,12 @@ allocauto(Prog* ptxt) Node* n; vlong w; - if(curfn->dcl == nil) { - stksize = 0; - stkptrsize = 0; + stksize = 0; + stkptrsize = 0; + stkzerosize = 0; + + if(curfn->dcl == nil) return; - } // Mark the PAUTO's unused. for(ll=curfn->dcl; ll != nil; ll=ll->next) @@ -421,6 +428,11 @@ allocauto(Prog* ptxt) ll->n->used = 0; markautoused(ptxt); + + // TODO: Remove when liveness analysis sets needzero instead. + for(ll=curfn->dcl; ll != nil; ll=ll->next) + if (ll->n->class == PAUTO) + ll->n->needzero = 1; // ll->n->addrtaken; listsort(&curfn->dcl, cmpstackvar); @@ -430,8 +442,6 @@ allocauto(Prog* ptxt) if (n->class == PAUTO && n->op == ONAME && !n->used) { // No locals used at all curfn->dcl = nil; - stksize = 0; - stkptrsize = 0; fixautoused(ptxt); return; } @@ -446,8 +456,6 @@ allocauto(Prog* ptxt) } // Reassign stack offsets of the locals that are still there. - stksize = 0; - stkptrsize = 0; for(ll = curfn->dcl; ll != nil; ll=ll->next) { n = ll->n; if (n->class != PAUTO || n->op != ONAME) @@ -459,8 +467,11 @@ allocauto(Prog* ptxt) fatal("bad width"); stksize += w; stksize = rnd(stksize, n->type->align); - if(haspointers(n->type)) + if(haspointers(n->type)) { stkptrsize = stksize; + if(n->needzero) + stkzerosize = stksize; + } if(thechar == '5') stksize = rnd(stksize, widthptr); if(stksize >= (1ULL<<31)) { @@ -471,6 +482,7 @@ allocauto(Prog* ptxt) } stksize = rnd(stksize, widthptr); stkptrsize = rnd(stkptrsize, widthptr); + stkzerosize = rnd(stkzerosize, widthptr); fixautoused(ptxt); |
