Commit 3b4d7926 authored by Russ Cox's avatar Russ Cox

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
parent a96d850a
...@@ -35,11 +35,11 @@ defframe(Prog *ptxt, Bvec *bv) ...@@ -35,11 +35,11 @@ defframe(Prog *ptxt, Bvec *bv)
p = ptxt; p = ptxt;
while(p->link->as == AFUNCDATA || p->link->as == APCDATA || p->link->as == ATYPE) while(p->link->as == AFUNCDATA || p->link->as == APCDATA || p->link->as == ATYPE)
p = p->link; 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, 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->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; p->reg = 1;
p1 = p = appendp(p, AMOVW, D_REG, 0, 0, D_OREG, 1, 4); p1 = p = appendp(p, AMOVW, D_REG, 0, 0, D_OREG, 1, 4);
p->scond |= C_PBIT; p->scond |= C_PBIT;
...@@ -49,13 +49,13 @@ defframe(Prog *ptxt, Bvec *bv) ...@@ -49,13 +49,13 @@ defframe(Prog *ptxt, Bvec *bv)
patch(p, p1); patch(p, p1);
} else { } else {
first = 1; 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(bvget(bv, j) || bvget(bv, j+1)) {
if(first) { if(first) {
p = appendp(p, AMOVW, D_CONST, NREG, 0, D_REG, 0, 0); p = appendp(p, AMOVW, D_CONST, NREG, 0, D_REG, 0, 0);
first = 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);
} }
} }
} }
......
...@@ -30,16 +30,16 @@ defframe(Prog *ptxt, Bvec *bv) ...@@ -30,16 +30,16 @@ defframe(Prog *ptxt, Bvec *bv)
// so that garbage collector only sees initialized values // so that garbage collector only sees initialized values
// when it looks for pointers. // when it looks for pointers.
p = ptxt; 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, 0, D_AX, 0);
p = appendp(p, AMOVQ, D_CONST, stkptrsize/widthptr, D_CX, 0); p = appendp(p, AMOVQ, D_CONST, stkzerosize/widthptr, D_CX, 0);
p = appendp(p, ALEAQ, D_SP+D_INDIR, frame-stkptrsize, D_DI, 0); p = appendp(p, ALEAQ, D_SP+D_INDIR, frame-stkzerosize, D_DI, 0);
p = appendp(p, AREP, D_NONE, 0, D_NONE, 0); p = appendp(p, AREP, D_NONE, 0, D_NONE, 0);
appendp(p, ASTOSQ, D_NONE, 0, D_NONE, 0); appendp(p, ASTOSQ, D_NONE, 0, D_NONE, 0);
} else { } 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)) 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);
} }
} }
......
...@@ -32,16 +32,16 @@ defframe(Prog *ptxt, Bvec *bv) ...@@ -32,16 +32,16 @@ defframe(Prog *ptxt, Bvec *bv)
// so that garbage collector only sees initialized values // so that garbage collector only sees initialized values
// when it looks for pointers. // when it looks for pointers.
p = ptxt; 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, 0, D_AX, 0);
p = appendp(p, AMOVL, D_CONST, stkptrsize/widthptr, D_CX, 0); p = appendp(p, AMOVL, D_CONST, stkzerosize/widthptr, D_CX, 0);
p = appendp(p, ALEAL, D_SP+D_INDIR, frame-stkptrsize, D_DI, 0); p = appendp(p, ALEAL, D_SP+D_INDIR, frame-stkzerosize, D_DI, 0);
p = appendp(p, AREP, D_NONE, 0, D_NONE, 0); p = appendp(p, AREP, D_NONE, 0, D_NONE, 0);
appendp(p, ASTOSL, D_NONE, 0, D_NONE, 0); appendp(p, ASTOSL, D_NONE, 0, D_NONE, 0);
} else { } 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)) 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);
} }
} }
......
...@@ -270,6 +270,7 @@ struct Node ...@@ -270,6 +270,7 @@ struct Node
uchar dupok; // duplicate definitions ok (for func) uchar dupok; // duplicate definitions ok (for func)
schar likely; // likeliness of if statement schar likely; // likeliness of if statement
uchar hasbreak; // has break statement uchar hasbreak; // has break statement
uchar needzero; // if it contains pointers, needs to be zeroed on function entry
uint esc; // EscXXX uint esc; // EscXXX
int funcdepth; int funcdepth;
...@@ -940,7 +941,8 @@ EXTERN NodeList* lastconst; ...@@ -940,7 +941,8 @@ EXTERN NodeList* lastconst;
EXTERN Node* lasttype; EXTERN Node* lasttype;
EXTERN vlong maxarg; EXTERN vlong maxarg;
EXTERN vlong stksize; // stack size for current frame 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 blockgen; // max block number
EXTERN int32 block; // current block number EXTERN int32 block; // current block number
EXTERN int hasdefer; // flag that curfn has defer statetment EXTERN int hasdefer; // flag that curfn has defer statetment
......
...@@ -367,11 +367,11 @@ dumpgclocals(Node* fn, Sym *sym) ...@@ -367,11 +367,11 @@ dumpgclocals(Node* fn, Sym *sym)
// Sort the list of stack variables. Autos after anything else, // Sort the list of stack variables. Autos after anything else,
// within autos, unused after used, within used, things with // 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 // Because autos are laid out in decreasing addresses
// on the stack, pointers first and decreasing size // on the stack, pointers first, zeroed things first and decreasing size
// really means, in memory, pointers near the top of the // really means, in memory, things with pointers needing zeroing at
// stack and increasing in size. // the top of the stack and increasing in size.
// Non-autos sort on offset. // Non-autos sort on offset.
static int static int
cmpstackvar(Node *a, Node *b) cmpstackvar(Node *a, Node *b)
...@@ -394,6 +394,12 @@ cmpstackvar(Node *a, Node *b) ...@@ -394,6 +394,12 @@ cmpstackvar(Node *a, Node *b)
bp = haspointers(b->type); bp = haspointers(b->type);
if(ap != bp) if(ap != bp)
return bp - ap; return bp - ap;
ap = a->needzero;
bp = b->needzero;
if(ap != bp)
return bp - ap;
if(a->type->width < b->type->width) if(a->type->width < b->type->width)
return +1; return +1;
if(a->type->width > b->type->width) if(a->type->width > b->type->width)
...@@ -409,11 +415,12 @@ allocauto(Prog* ptxt) ...@@ -409,11 +415,12 @@ allocauto(Prog* ptxt)
Node* n; Node* n;
vlong w; vlong w;
if(curfn->dcl == nil) { stksize = 0;
stksize = 0; stkptrsize = 0;
stkptrsize = 0; stkzerosize = 0;
if(curfn->dcl == nil)
return; return;
}
// Mark the PAUTO's unused. // Mark the PAUTO's unused.
for(ll=curfn->dcl; ll != nil; ll=ll->next) for(ll=curfn->dcl; ll != nil; ll=ll->next)
...@@ -421,6 +428,11 @@ allocauto(Prog* ptxt) ...@@ -421,6 +428,11 @@ allocauto(Prog* ptxt)
ll->n->used = 0; ll->n->used = 0;
markautoused(ptxt); 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); listsort(&curfn->dcl, cmpstackvar);
...@@ -430,8 +442,6 @@ allocauto(Prog* ptxt) ...@@ -430,8 +442,6 @@ allocauto(Prog* ptxt)
if (n->class == PAUTO && n->op == ONAME && !n->used) { if (n->class == PAUTO && n->op == ONAME && !n->used) {
// No locals used at all // No locals used at all
curfn->dcl = nil; curfn->dcl = nil;
stksize = 0;
stkptrsize = 0;
fixautoused(ptxt); fixautoused(ptxt);
return; return;
} }
...@@ -446,8 +456,6 @@ allocauto(Prog* ptxt) ...@@ -446,8 +456,6 @@ allocauto(Prog* ptxt)
} }
// Reassign stack offsets of the locals that are still there. // Reassign stack offsets of the locals that are still there.
stksize = 0;
stkptrsize = 0;
for(ll = curfn->dcl; ll != nil; ll=ll->next) { for(ll = curfn->dcl; ll != nil; ll=ll->next) {
n = ll->n; n = ll->n;
if (n->class != PAUTO || n->op != ONAME) if (n->class != PAUTO || n->op != ONAME)
...@@ -459,8 +467,11 @@ allocauto(Prog* ptxt) ...@@ -459,8 +467,11 @@ allocauto(Prog* ptxt)
fatal("bad width"); fatal("bad width");
stksize += w; stksize += w;
stksize = rnd(stksize, n->type->align); stksize = rnd(stksize, n->type->align);
if(haspointers(n->type)) if(haspointers(n->type)) {
stkptrsize = stksize; stkptrsize = stksize;
if(n->needzero)
stkzerosize = stksize;
}
if(thechar == '5') if(thechar == '5')
stksize = rnd(stksize, widthptr); stksize = rnd(stksize, widthptr);
if(stksize >= (1ULL<<31)) { if(stksize >= (1ULL<<31)) {
...@@ -471,6 +482,7 @@ allocauto(Prog* ptxt) ...@@ -471,6 +482,7 @@ allocauto(Prog* ptxt)
} }
stksize = rnd(stksize, widthptr); stksize = rnd(stksize, widthptr);
stkptrsize = rnd(stkptrsize, widthptr); stkptrsize = rnd(stkptrsize, widthptr);
stkzerosize = rnd(stkzerosize, widthptr);
fixautoused(ptxt); fixautoused(ptxt);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment