Skip to content

Commit

Permalink
cmd/gc: racewalk: do not double function calls
Browse files Browse the repository at this point in the history
Current racewalk transformation looks like:
x := <-makeChan().c
\/\/\/\/\/\/\/\/\/
runtime.raceread(&makeChan().c)
x := <-makeChan().c
and so makeChan() is called twice.
With this CL the transformation looks like:
x := <-makeChan().c
\/\/\/\/\/\/\/\/\/
chan *tmp = &(makeChan().c)
raceread(&*tmp)
x := <-(*tmp)
Fixes #4245.

R=golang-dev, rsc
CC=golang-dev
https://golang.org/cl/6822075
  • Loading branch information
dvyukov committed Nov 7, 2012
1 parent 703043c commit abb313f
Showing 1 changed file with 85 additions and 12 deletions.
97 changes: 85 additions & 12 deletions src/cmd/gc/racewalk.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,12 @@

static void racewalklist(NodeList *l, NodeList **init);
static void racewalknode(Node **np, NodeList **init, int wr, int skip);
static int callinstr(Node *n, NodeList **init, int wr, int skip);
static int callinstr(Node **n, NodeList **init, int wr, int skip);
static Node* uintptraddr(Node *n);
static Node* basenod(Node *n);
static void foreach(Node *n, void(*f)(Node*, void*), void *c);
static void hascallspred(Node *n, void *c);
static Node* detachexpr(Node *n, NodeList **init);

static const char *omitPkgs[] = {"runtime", "runtime/race", "sync", "sync/atomic"};

Expand Down Expand Up @@ -196,18 +199,18 @@ racewalknode(Node **np, NodeList **init, int wr, int skip)
goto ret;

case ODOT:
callinstr(n, init, wr, skip);
racewalknode(&n->left, init, 0, 1);
callinstr(&n, init, wr, skip);
goto ret;

case ODOTPTR: // dst = (*x).f with implicit *; otherwise it's ODOT+OIND
callinstr(n, init, wr, skip);
racewalknode(&n->left, init, 0, 0);
callinstr(&n, init, wr, skip);
goto ret;

case OIND: // *p
callinstr(n, init, wr, skip);
racewalknode(&n->left, init, 0, 0);
callinstr(&n, init, wr, skip);
goto ret;

case OLEN:
Expand All @@ -223,7 +226,7 @@ racewalknode(Node **np, NodeList **init, int wr, int skip)
n1 = nod(OIND, n1, N);
n1 = nod(OIND, n1, N);
typecheck(&n1, Erv);
callinstr(n1, init, 0, skip);
callinstr(&n1, init, 0, skip);
*/
}
goto ret;
Expand Down Expand Up @@ -257,7 +260,7 @@ racewalknode(Node **np, NodeList **init, int wr, int skip)
goto ret;

case ONAME:
callinstr(n, init, wr, skip);
callinstr(&n, init, wr, skip);
goto ret;

case OCONV:
Expand All @@ -276,11 +279,11 @@ racewalknode(Node **np, NodeList **init, int wr, int skip)
goto ret;

case OINDEX:
if(n->left->type->etype != TSTRING)
callinstr(n, init, wr, skip);
if(!isfixedarray(n->left->type))
racewalknode(&n->left, init, 0, 0);
racewalknode(&n->right, init, 0, 0);
if(n->left->type->etype != TSTRING)
callinstr(&n, init, wr, skip);
goto ret;

case OSLICE:
Expand Down Expand Up @@ -376,12 +379,13 @@ racewalknode(Node **np, NodeList **init, int wr, int skip)
}

static int
callinstr(Node *n, NodeList **init, int wr, int skip)
callinstr(Node **np, NodeList **init, int wr, int skip)
{
Node *f, *b;
Node *f, *b, *n;
Type *t, *t1;
int class, res;
int class, res, hascalls;

n = *np;
//print("callinstr for %N [ %s ] etype=%d class=%d\n",
// n, opnames[n->op], n->type ? n->type->etype : -1, n->class);

Expand All @@ -402,11 +406,17 @@ callinstr(Node *n, NodeList **init, int wr, int skip)
}
if(t->etype == TSTRUCT) {
res = 0;
hascalls = 0;
foreach(n, hascallspred, &hascalls);
if(hascalls) {
n = detachexpr(n, init);
*np = n;
}
for(t1=t->type; t1; t1=t1->down) {
if(t1->sym && strcmp(t1->sym->name, "_")) {
n = treecopy(n);
f = nod(OXDOT, n, newname(t1->sym));
if(callinstr(f, init, wr, 0)) {
if(callinstr(&f, init, wr, 0)) {
typecheck(&f, Erv);
res = 1;
}
Expand All @@ -423,6 +433,12 @@ callinstr(Node *n, NodeList **init, int wr, int skip)
// the heap or not is impossible to know at compile time
if((class&PHEAP) || class == PPARAMREF || class == PEXTERN
|| b->type->etype == TARRAY || b->op == ODOTPTR || b->op == OIND || b->op == OXDOT) {
hascalls = 0;
foreach(n, hascallspred, &hascalls);
if(hascalls) {
n = detachexpr(n, init);
*np = n;
}
n = treecopy(n);
f = mkcall(wr ? "racewrite" : "raceread", T, nil, uintptraddr(n));
//typecheck(&f, Etop);
Expand Down Expand Up @@ -459,3 +475,60 @@ basenod(Node *n)
}
return n;
}

static Node*
detachexpr(Node *n, NodeList **init)
{
Node *addr, *as, *ind, *l;

addr = nod(OADDR, n, N);
l = temp(ptrto(n->type));
as = nod(OAS, l, addr);
typecheck(&as, Etop);
walkexpr(&as, init);
*init = list(*init, as);
ind = nod(OIND, l, N);
typecheck(&ind, Erv);
walkexpr(&ind, init);
return ind;
}

static void
foreachnode(Node *n, void(*f)(Node*, void*), void *c)
{
if(n)
f(n, c);
}

static void
foreachlist(NodeList *l, void(*f)(Node*, void*), void *c)
{
for(; l; l = l->next)
foreachnode(l->n, f, c);
}

static void
foreach(Node *n, void(*f)(Node*, void*), void *c)
{
foreachlist(n->ninit, f, c);
foreachnode(n->left, f, c);
foreachnode(n->right, f, c);
foreachlist(n->list, f, c);
foreachnode(n->ntest, f, c);
foreachnode(n->nincr, f, c);
foreachlist(n->nbody, f, c);
foreachlist(n->nelse, f, c);
foreachlist(n->rlist, f, c);
}

static void
hascallspred(Node *n, void *c)
{
switch(n->op) {
case OCALL:
case OCALLFUNC:
case OCALLMETH:
case OCALLINTER:
(*(int*)c)++;
}
}

0 comments on commit abb313f

Please sign in to comment.