Commit c0b3c171 authored by Rémy Oudompheng's avatar Rémy Oudompheng

cmd/gc: instrument logical && and ||.

The right operand of a && and || is only executed conditionnally,
so the instrumentation must be more careful. In particular
it should not turn nodes assumed to be cheap after walk into
expensive ones.

Update #4228

R=dvyukov, golang-dev
CC=golang-dev
https://golang.org/cl/7986043
parent 4cb921bb
...@@ -26,6 +26,7 @@ static Node* uintptraddr(Node *n); ...@@ -26,6 +26,7 @@ static Node* uintptraddr(Node *n);
static Node* basenod(Node *n); static Node* basenod(Node *n);
static void foreach(Node *n, void(*f)(Node*, void*), void *c); static void foreach(Node *n, void(*f)(Node*, void*), void *c);
static void hascallspred(Node *n, void *c); static void hascallspred(Node *n, void *c);
static void appendinit(Node **np, NodeList *init);
static Node* detachexpr(Node *n, NodeList **init); static Node* detachexpr(Node *n, NodeList **init);
// Do not instrument the following packages at all, // Do not instrument the following packages at all,
...@@ -139,7 +140,7 @@ racewalknode(Node **np, NodeList **init, int wr, int skip) ...@@ -139,7 +140,7 @@ racewalknode(Node **np, NodeList **init, int wr, int skip)
racewalknode(&n->left, init, 1, 0); racewalknode(&n->left, init, 1, 0);
racewalknode(&n->right, init, 0, 0); racewalknode(&n->right, init, 0, 0);
goto ret; goto ret;
case OCFUNC: case OCFUNC:
// can't matter // can't matter
goto ret; goto ret;
...@@ -255,9 +256,13 @@ racewalknode(Node **np, NodeList **init, int wr, int skip) ...@@ -255,9 +256,13 @@ racewalknode(Node **np, NodeList **init, int wr, int skip)
case OANDAND: case OANDAND:
case OOROR: case OOROR:
racewalknode(&n->left, init, wr, 0); racewalknode(&n->left, init, wr, 0);
// It requires more complex tree transformation, // walk has ensured the node has moved to a location where
// because we don't know whether it will be executed or not. // side effects are safe.
//racewalknode(&n->right, init, wr, 0); // n->right may not be executed,
// so instrumentation goes to n->right->ninit, not init.
l = nil;
racewalknode(&n->right, &l, wr, 0);
appendinit(&n->right, l);
goto ret; goto ret;
case ONAME: case ONAME:
...@@ -398,7 +403,6 @@ ret: ...@@ -398,7 +403,6 @@ ret:
racewalklist(n->nbody, nil); racewalklist(n->nbody, nil);
racewalklist(n->nelse, nil); racewalklist(n->nelse, nil);
racewalklist(n->rlist, nil); racewalklist(n->rlist, nil);
*np = n; *np = n;
} }
...@@ -575,3 +579,30 @@ hascallspred(Node *n, void *c) ...@@ -575,3 +579,30 @@ hascallspred(Node *n, void *c)
(*(int*)c)++; (*(int*)c)++;
} }
} }
// appendinit is like addinit in subr.c
// but appends rather than prepends.
static void
appendinit(Node **np, NodeList *init)
{
Node *n;
if(init == nil)
return;
n = *np;
switch(n->op) {
case ONAME:
case OLITERAL:
// There may be multiple refs to this node;
// introduce OCONVNOP to hold init list.
n = nod(OCONVNOP, n, N);
n->type = n->left->type;
n->typecheck = 1;
*np = n;
break;
}
n->ninit = concat(n->ninit, init);
n->ullman = UINF;
}
...@@ -1759,6 +1759,13 @@ ullmancalc(Node *n) ...@@ -1759,6 +1759,13 @@ ullmancalc(Node *n)
case OCALLINTER: case OCALLINTER:
ul = UINF; ul = UINF;
goto out; goto out;
case OANDAND:
case OOROR:
// hard with race detector
if(flag_race) {
ul = UINF;
goto out;
}
} }
ul = 1; ul = 1;
if(n->left != N) if(n->left != N)
......
...@@ -970,8 +970,7 @@ func TestRaceAnd(t *testing.T) { ...@@ -970,8 +970,7 @@ func TestRaceAnd(t *testing.T) {
<-c <-c
} }
// OANDAND is not instrumented in the compiler. func TestRaceAnd2(t *testing.T) {
func TestRaceFailingAnd2(t *testing.T) {
c := make(chan bool) c := make(chan bool)
x, y := 0, 0 x, y := 0, 0
go func() { go func() {
...@@ -1007,8 +1006,7 @@ func TestRaceOr(t *testing.T) { ...@@ -1007,8 +1006,7 @@ func TestRaceOr(t *testing.T) {
<-c <-c
} }
// OOROR is not instrumented in the compiler. func TestRaceOr2(t *testing.T) {
func TestRaceFailingOr2(t *testing.T) {
c := make(chan bool) c := make(chan bool)
x, y := 0, 0 x, y := 0, 0
go func() { go func() {
......
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