Commit b7603cfc authored by Russ Cox's avatar Russ Cox

cmd/gc: add GOEXPERIMENT=zerostack to clear stack on function entry

This is expensive but it might be useful in cases where
people are suffering from false positives during garbage
collection and are willing to trade the CPU time for getting
rid of the false positives.

On the other hand it only eliminates false positives caused
by other function calls, not false positives caused by dead
temporaries stored in the current function call.

The 5g/6g/8g changes were pulled out of the history, from
the last time we needed to do this (to work around a goto bug).
The code in go.h, lex.c, pgen.c is new but tiny.

R=ken2
CC=golang-dev
https://golang.org/cl/6938073
parent 5a2c275b
......@@ -174,6 +174,64 @@ newplist(void)
return pl;
}
void
clearstk(void)
{
Plist *pl;
Prog *p, *p1, *p2, *p3;
Node dst, end, zero, con;
if(plast->firstpc->to.offset <= 0)
return;
// reestablish context for inserting code
// at beginning of function.
pl = plast;
p1 = pl->firstpc;
p2 = p1->link;
pc = mal(sizeof(*pc));
clearp(pc);
p1->link = pc;
// zero stack frame
// MOVW $4(SP), R1
nodreg(&dst, types[tptr], 1);
p = gins(AMOVW, N, &dst);
p->from.type = D_CONST;
p->from.reg = REGSP;
p->from.offset = 4;
// MOVW $n(R1), R2
nodreg(&end, types[tptr], 2);
p = gins(AMOVW, N, &end);
p->from.type = D_CONST;
p->from.reg = 1;
p->from.offset = p1->to.offset;
// MOVW $0, R3
nodreg(&zero, types[TUINT32], 3);
nodconst(&con, types[TUINT32], 0);
gmove(&con, &zero);
// L:
// MOVW.P R3, 0(R1) +4
// CMP R1, R2
// BNE L
p = gins(AMOVW, &zero, &dst);
p->to.type = D_OREG;
p->to.offset = 4;
p->scond |= C_PBIT;
p3 = p;
p = gins(ACMP, &dst, N);
raddr(&end, p);
patch(gbranch(ABNE, T, 0), p3);
// continue with original code.
gins(ANOP, N, N)->link = p2;
pc = P;
}
void
gused(Node *n)
{
......
......@@ -172,6 +172,44 @@ newplist(void)
return pl;
}
void
clearstk(void)
{
Plist *pl;
Prog *p1, *p2;
Node sp, di, cx, con, ax;
if((uint32)plast->firstpc->to.offset <= 0)
return;
// reestablish context for inserting code
// at beginning of function.
pl = plast;
p1 = pl->firstpc;
p2 = p1->link;
pc = mal(sizeof(*pc));
clearp(pc);
p1->link = pc;
// zero stack frame
nodreg(&sp, types[tptr], D_SP);
nodreg(&di, types[tptr], D_DI);
nodreg(&cx, types[TUINT64], D_CX);
nodconst(&con, types[TUINT64], (uint32)p1->to.offset / widthptr);
gins(ACLD, N, N);
gins(AMOVQ, &sp, &di);
gins(AMOVQ, &con, &cx);
nodconst(&con, types[TUINT64], 0);
nodreg(&ax, types[TUINT64], D_AX);
gins(AMOVQ, &con, &ax);
gins(AREP, N, N);
gins(ASTOSQ, N, N);
// continue with original code.
gins(ANOP, N, N)->link = p2;
pc = P;
}
void
gused(Node *n)
{
......
......@@ -173,6 +173,44 @@ newplist(void)
return pl;
}
void
clearstk(void)
{
Plist *pl;
Prog *p1, *p2;
Node sp, di, cx, con, ax;
if(plast->firstpc->to.offset <= 0)
return;
// reestablish context for inserting code
// at beginning of function.
pl = plast;
p1 = pl->firstpc;
p2 = p1->link;
pc = mal(sizeof(*pc));
clearp(pc);
p1->link = pc;
// zero stack frame
nodreg(&sp, types[tptr], D_SP);
nodreg(&di, types[tptr], D_DI);
nodreg(&cx, types[TUINT32], D_CX);
nodconst(&con, types[TUINT32], p1->to.offset / widthptr);
gins(ACLD, N, N);
gins(AMOVL, &sp, &di);
gins(AMOVL, &con, &cx);
nodconst(&con, types[TUINT32], 0);
nodreg(&ax, types[TUINT32], D_AX);
gins(AMOVL, &con, &ax);
gins(AREP, N, N);
gins(ASTOSL, N, N);
// continue with original code.
gins(ANOP, N, N)->link = p2;
pc = P;
}
void
gused(Node *n)
{
......
......@@ -937,6 +937,7 @@ EXTERN int funcdepth;
EXTERN int typecheckok;
EXTERN int compiling_runtime;
EXTERN int compiling_wrappers;
EXTERN int zerostack_enabled;
EXTERN int nointerface;
EXTERN int fieldtrack_enabled;
......@@ -1092,6 +1093,7 @@ void genlist(NodeList *l);
Node* sysfunc(char *name);
void tempname(Node *n, Type *t);
Node* temp(Type*);
void clearstk(void);
/*
* init.c
......
......@@ -41,6 +41,7 @@ static struct {
} exper[] = {
// {"rune32", &rune32},
{"fieldtrack", &fieldtrack_enabled},
{"zerostack", &zerostack_enabled},
{nil, nil},
};
......
......@@ -141,6 +141,9 @@ compile(Node *fn)
if(0)
frame(0);
if(zerostack_enabled)
clearstk();
ret:
lineno = lno;
}
......
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