There is more zeroing than I would like right now -
temporaries used for the new map and channel runtime
calls need to be eliminated - but it will do for now.
This CL only has an effect if you are building with
GOEXPERIMENT=precisestack ./all.bash
(or make.bash). It costs about 5% in the overall time
spent in all.bash. That number will come down before
we make it on by default, but this should be enough for
Keith to try using the precise maps for copying stacks.
amd64 only (and it's not really great generated code).
TBR=khr, iant
CC=golang-codereviews
https://golang.org/cl/
56430043
#include "gg.h"
#include "opt.h"
+static Prog *appendpp(Prog*, int, int, vlong, int, vlong);
+
void
defframe(Prog *ptxt)
{
uint32 frame;
+ Prog *p;
// fill in argument size
ptxt->to.offset = rnd(curfn->type->argwid, widthptr);
ptxt->to.offset <<= 32;
frame = rnd(stksize+maxarg, widthptr);
ptxt->to.offset |= frame;
+
+ // insert code to contain ambiguously live variables
+ // so that garbage collector only sees initialized values
+ // when it looks for pointers.
+ p = ptxt;
+ if(stkzerosize > 0) {
+ p = appendpp(p, AMOVQ, D_CONST, 0, D_AX, 0);
+ p = appendpp(p, AMOVQ, D_CONST, stkzerosize/widthptr, D_CX, 0);
+ p = appendpp(p, ALEAQ, D_SP+D_INDIR, frame-stkzerosize, D_DI, 0);
+ p = appendpp(p, AREP, D_NONE, 0, D_NONE, 0);
+ appendpp(p, ASTOSQ, D_NONE, 0, D_NONE, 0);
+ }
+}
+
+static Prog*
+appendpp(Prog *p, int as, int ftype, vlong foffset, int ttype, vlong toffset)
+{
+ Prog *q;
+ q = mal(sizeof(*q));
+ clearp(q);
+ q->as = as;
+ q->lineno = p->lineno;
+ q->from.type = ftype;
+ q->from.offset = foffset;
+ q->to.type = ttype;
+ q->to.offset = toffset;
+ q->link = p->link;
+ p->link = q;
+ return q;
}
// Sweep the prog list to mark any used nodes.
if(debug['g'])
dump("\nclearfat", nl);
+ gfatvardef(nl);
w = nl->type->width;
// Avoid taking the address for simple enough types.
if(componentgen(N, nl))
return;
- gfatvardef(nl);
-
c = w % 8; // bytes
q = w / 8; // quads
bvor(all, all, avarinit);
if(issafepoint(p)) {
- if(debuglive >= 3) {
- // Diagnose ambiguously live variables (any &^ all).
- // livein and liveout are dead here and used as temporaries.
+ // Annotate ambiguously live variables so that they can
+ // be zeroed at function entry.
+ // livein and liveout are dead here and used as temporaries.
+ // For now, only enabled when using GOEXPERIMENT=precisestack
+ // during make.bash / all.bash.
+ if(precisestack_enabled) {
bvresetall(livein);
bvandnot(liveout, any, all);
- if(bvcmp(livein, liveout) != 0) {
+ if(!bvisempty(liveout)) {
for(pos = 0; pos < liveout->n; pos++) {
- if(bvget(liveout, pos)) {
- n = *(Node**)arrayget(lv->vars, pos);
- if(!n->diag && strncmp(n->sym->name, "autotmp_", 8) != 0) {
- n->diag = 1;
+ bvset(all, pos); // silence future warnings in this block
+ if(!bvget(liveout, pos))
+ continue;
+ n = *(Node**)arrayget(lv->vars, pos);
+ if(!n->needzero) {
+ n->needzero = 1;
+ if(debuglive >= 3)
warnl(p->lineno, "%N: %lN is ambiguously live", curfn->nname, n);
- }
}
- bvset(all, pos); // silence future warnings in this block
}
}
}
-
+
// Allocate a bit vector for each class and facet of
// value we are tracking.
stackmap = runtime·funcdata(f, FUNCDATA_ArgsPointerMaps);
if(stackmap != nil) {
bv = stackmapdata(stackmap, pcdata);
- scanbitvector(frame->argp, bv, false, wbufp);
+ scanbitvector(frame->argp, bv, true, wbufp);
} else
enqueue1(wbufp, (Obj){frame->argp, frame->arglen, 0});
}