Commit f91e682c authored by Russ Cox's avatar Russ Cox

cmd/gc: make bitmaps shorter

Sort non-pointer-containing data to the low end of the
stack frame, and make the bitmaps only cover the
pointer-containing top end.

Generates significantly less garbage collection bitmap
for programs with large byte buffers on the stack.

Only 2% shorter for godoc, but 99.99998% shorter
in some test cases.

Fixes arm build.

TBR=golang-dev
CC=cshapiro, golang-dev, iant
https://golang.org/cl/12541047
parent 9a9e541c
...@@ -153,6 +153,7 @@ struct Type ...@@ -153,6 +153,7 @@ struct Type
uchar broke; // broken type definition. uchar broke; // broken type definition.
uchar isddd; // TFIELD is ... argument uchar isddd; // TFIELD is ... argument
uchar align; uchar align;
uchar haspointers; // 0 unknown, 1 no, 2 yes
Node* nod; // canonical OTYPE node Node* nod; // canonical OTYPE node
Type* orig; // original type (type literal or predefined type) Type* orig; // original type (type literal or predefined type)
...@@ -937,6 +938,7 @@ EXTERN NodeList* lastconst; ...@@ -937,6 +938,7 @@ 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 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
......
...@@ -336,12 +336,12 @@ dumpgclocals(Node* fn, Sym *sym) ...@@ -336,12 +336,12 @@ dumpgclocals(Node* fn, Sym *sym)
int32 i; int32 i;
int off; int off;
bv = bvalloc(rnd(stksize, widthptr) / widthptr); bv = bvalloc(stkptrsize / widthptr);
for(ll = fn->dcl; ll != nil; ll = ll->next) { for(ll = fn->dcl; ll != nil; ll = ll->next) {
node = ll->n; node = ll->n;
if(node->class == PAUTO && node->op == ONAME) { if(node->class == PAUTO && node->op == ONAME) {
if(haspointers(node->type)) { if(haspointers(node->type)) {
xoffset = node->xoffset + rnd(stksize,widthptr); xoffset = node->xoffset + stksize;
walktype1(node->type, &xoffset, bv); walktype1(node->type, &xoffset, bv);
} }
} }
...@@ -354,25 +354,40 @@ dumpgclocals(Node* fn, Sym *sym) ...@@ -354,25 +354,40 @@ dumpgclocals(Node* fn, Sym *sym)
ggloblsym(sym, off, 0, 1); ggloblsym(sym, off, 0, 1);
} }
// 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, and within used on reverse alignment. // within autos, unused after used, within used, things with
// non-autos sort on offset. // pointers 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.
// Non-autos sort on offset.
static int static int
cmpstackvar(Node *a, Node *b) cmpstackvar(Node *a, Node *b)
{ {
int ap, bp;
if (a->class != b->class) if (a->class != b->class)
return (a->class == PAUTO) ? 1 : -1; return (a->class == PAUTO) ? +1 : -1;
if (a->class != PAUTO) { if (a->class != PAUTO) {
if (a->xoffset < b->xoffset) if (a->xoffset < b->xoffset)
return -1; return -1;
if (a->xoffset > b->xoffset) if (a->xoffset > b->xoffset)
return 1; return +1;
return 0; return 0;
} }
if ((a->used == 0) != (b->used == 0)) if ((a->used == 0) != (b->used == 0))
return b->used - a->used; return b->used - a->used;
return b->type->align - a->type->align;
ap = haspointers(a->type);
bp = haspointers(b->type);
if(ap != bp)
return bp - ap;
if(a->type->width < b->type->width)
return +1;
if(a->type->width > b->type->width)
return -1;
return 0;
} }
// TODO(lvd) find out where the PAUTO/OLITERAL nodes come from. // TODO(lvd) find out where the PAUTO/OLITERAL nodes come from.
...@@ -382,9 +397,13 @@ allocauto(Prog* ptxt) ...@@ -382,9 +397,13 @@ allocauto(Prog* ptxt)
NodeList *ll; NodeList *ll;
Node* n; Node* n;
vlong w; vlong w;
vlong ptrlimit;
if(curfn->dcl == nil) if(curfn->dcl == nil) {
stksize = 0;
stkptrsize = 0;
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)
...@@ -402,6 +421,7 @@ allocauto(Prog* ptxt) ...@@ -402,6 +421,7 @@ allocauto(Prog* ptxt)
// No locals used at all // No locals used at all
curfn->dcl = nil; curfn->dcl = nil;
stksize = 0; stksize = 0;
stkptrsize = 0;
fixautoused(ptxt); fixautoused(ptxt);
return; return;
} }
...@@ -417,6 +437,7 @@ allocauto(Prog* ptxt) ...@@ -417,6 +437,7 @@ 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; stksize = 0;
ptrlimit = -1;
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)
...@@ -428,6 +449,8 @@ allocauto(Prog* ptxt) ...@@ -428,6 +449,8 @@ 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(ptrlimit < 0 && haspointers(n->type))
ptrlimit = stksize - w;
if(thechar == '5') if(thechar == '5')
stksize = rnd(stksize, widthptr); stksize = rnd(stksize, widthptr);
if(stksize >= (1ULL<<31)) { if(stksize >= (1ULL<<31)) {
...@@ -436,11 +459,18 @@ allocauto(Prog* ptxt) ...@@ -436,11 +459,18 @@ allocauto(Prog* ptxt)
} }
n->stkdelta = -stksize - n->xoffset; n->stkdelta = -stksize - n->xoffset;
} }
stksize = rnd(stksize, widthptr);
if(ptrlimit < 0)
stkptrsize = 0;
else
stkptrsize = stksize - ptrlimit;
stkptrsize = rnd(stkptrsize, widthptr);
fixautoused(ptxt); fixautoused(ptxt);
// The debug information needs accurate offsets on the symbols. // The debug information needs accurate offsets on the symbols.
for(ll = curfn->dcl ;ll != nil; ll=ll->next) { for(ll = curfn->dcl; ll != nil; ll=ll->next) {
if (ll->n->class != PAUTO || ll->n->op != ONAME) if (ll->n->class != PAUTO || ll->n->op != ONAME)
continue; continue;
ll->n->xoffset += ll->n->stkdelta; ll->n->xoffset += ll->n->stkdelta;
......
...@@ -459,6 +459,10 @@ int ...@@ -459,6 +459,10 @@ int
haspointers(Type *t) haspointers(Type *t)
{ {
Type *t1; Type *t1;
int ret;
if(t->haspointers != 0)
return t->haspointers - 1;
switch(t->etype) { switch(t->etype) {
case TINT: case TINT:
...@@ -477,16 +481,24 @@ haspointers(Type *t) ...@@ -477,16 +481,24 @@ haspointers(Type *t)
case TCOMPLEX64: case TCOMPLEX64:
case TCOMPLEX128: case TCOMPLEX128:
case TBOOL: case TBOOL:
return 0; ret = 0;
break;
case TARRAY: case TARRAY:
if(t->bound < 0) // slice if(t->bound < 0) { // slice
return 1; ret = 1;
return haspointers(t->type); break;
}
ret = haspointers(t->type);
break;
case TSTRUCT: case TSTRUCT:
for(t1=t->type; t1!=T; t1=t1->down) ret = 0;
if(haspointers(t1->type)) for(t1=t->type; t1!=T; t1=t1->down) {
return 1; if(haspointers(t1->type)) {
return 0; ret = 1;
break;
}
}
break;
case TSTRING: case TSTRING:
case TPTR32: case TPTR32:
case TPTR64: case TPTR64:
...@@ -496,8 +508,12 @@ haspointers(Type *t) ...@@ -496,8 +508,12 @@ haspointers(Type *t)
case TMAP: case TMAP:
case TFUNC: case TFUNC:
default: default:
return 1; ret = 1;
break;
} }
t->haspointers = 1+ret;
return ret;
} }
/* /*
......
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