Commit 7c79910c authored by Rémy Oudompheng's avatar Rémy Oudompheng

cmd/gc: fix race instrumentation of append and type switches.

The remaining issues are about runtime and sync package
instrumentation.

Update #4228

R=dvyukov, bradfitz
CC=golang-dev
https://golang.org/cl/8041043
parent 0657e7df
......@@ -133,7 +133,6 @@ racewalknode(Node **np, NodeList **init, int wr, int skip)
case OASOP:
case OAS:
case OAS2:
case OAS2DOTTYPE:
case OAS2RECV:
case OAS2FUNC:
case OAS2MAPR:
......@@ -186,12 +185,6 @@ racewalknode(Node **np, NodeList **init, int wr, int skip)
racewalknode(&n->left, init, 0, 0);
goto ret;
case OSWITCH:
if(n->ntest->op == OTYPESW)
// TODO(dvyukov): the expression can contain calls or reads.
return;
goto ret;
case ONOT:
case OMINUS:
case OPLUS:
......@@ -317,6 +310,10 @@ racewalknode(Node **np, NodeList **init, int wr, int skip)
racewalknode(&n->left, init, 0, 0);
goto ret;
case OTYPESW:
racewalknode(&n->right, init, 0, 0);
goto ret;
// should not appear in AST by now
case OSEND:
case ORECV:
......@@ -334,6 +331,7 @@ racewalknode(Node **np, NodeList **init, int wr, int skip)
case OMAKESLICE:
case OCALL:
case OCOPY:
case OAPPEND:
case ORUNESTR:
case OARRAYBYTESTR:
case OARRAYRUNESTR:
......@@ -344,6 +342,7 @@ racewalknode(Node **np, NodeList **init, int wr, int skip)
case OADDSTR:
case ODOTTYPE:
case ODOTTYPE2:
case OAS2DOTTYPE:
case OCALLPART: // lowered to PTRLIT
case OCLOSURE: // lowered to PTRLIT
case ORANGE: // lowered to ordinary for loop
......@@ -364,6 +363,7 @@ racewalknode(Node **np, NodeList **init, int wr, int skip)
case OIF:
case OCALLMETH:
case ORETURN:
case OSWITCH:
case OSELECT:
case OEMPTY:
case OBREAK:
......@@ -389,10 +389,6 @@ racewalknode(Node **np, NodeList **init, int wr, int skip)
case OLITERAL:
case OSLICESTR: // always preceded by bounds checking, avoid double instrumentation.
goto ret;
// unimplemented
case OAPPEND:
goto ret;
}
ret:
......@@ -448,6 +444,7 @@ callinstr(Node **np, NodeList **init, int wr, int skip)
if(isartificial(n))
return 0;
if(t->etype == TSTRUCT) {
// TODO: instrument arrays similarly.
// PARAMs w/o PHEAP are not interesting.
if(n->class == PPARAM || n->class == PPARAMOUT)
return 0;
......@@ -484,7 +481,7 @@ callinstr(Node **np, NodeList **init, int wr, int skip)
// that has got a pointer inside. Whether it points to
// 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) {
|| b->op == OINDEX || b->op == ODOTPTR || b->op == OIND || b->op == OXDOT) {
hascalls = 0;
foreach(n, hascallspred, &hascalls);
if(hascalls) {
......@@ -510,6 +507,8 @@ uintptraddr(Node *n)
return r;
}
// basenod returns the simplest child node of n pointing to the same
// memory area.
static Node*
basenod(Node *n)
{
......@@ -518,7 +517,7 @@ basenod(Node *n)
n = n->left;
continue;
}
if(n->op == OINDEX) {
if(n->op == OINDEX && isfixedarray(n->type)) {
n = n->left;
continue;
}
......
......@@ -227,6 +227,37 @@ func TestRaceCaseFallthrough(t *testing.T) {
<-ch
}
func TestRaceCaseType(t *testing.T) {
var x, y int
var i interface{} = x
c := make(chan int, 1)
go func() {
switch i.(type) {
case nil:
case int:
}
c <- 1
}()
i = y
<-c
}
func TestRaceCaseTypeBody(t *testing.T) {
var x, y int
var i interface{} = &x
c := make(chan int, 1)
go func() {
switch i := i.(type) {
case nil:
case *int:
*i = y
}
c <- 1
}()
x = y
<-c
}
func TestNoRaceRange(t *testing.T) {
ch := make(chan int, 3)
a := [...]int{1, 2, 3}
......@@ -1446,6 +1477,21 @@ func TestRaceFailingSliceStruct(t *testing.T) {
<-c
}
func TestRaceAppendSliceStruct(t *testing.T) {
type X struct {
x, y int
}
c := make(chan bool, 1)
x := make([]X, 10)
go func() {
y := make([]X, 0, 10)
y = append(y, x...)
c <- true
}()
x[1].y = 42
<-c
}
func TestRaceStructInd(t *testing.T) {
c := make(chan bool, 1)
type Item struct {
......
......@@ -338,8 +338,7 @@ func TestRaceSliceVarCopy2(t *testing.T) {
<-c
}
// Not implemented.
func TestRaceFailingSliceAppend(t *testing.T) {
func TestRaceSliceAppend(t *testing.T) {
c := make(chan bool, 1)
s := make([]int, 10, 20)
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