From: Rémy Oudompheng Date: Wed, 27 Mar 2013 19:33:17 +0000 (+0100) Subject: cmd/gc: fix race instrumentation of append and type switches. X-Git-Tag: go1.1rc2~310 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=7c79910cb9abbac2f525c2b2ecad188ff27eb8af;p=gostls13.git 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 --- diff --git a/src/cmd/gc/racewalk.c b/src/cmd/gc/racewalk.c index fee5cf4226..5d4f62e761 100644 --- a/src/cmd/gc/racewalk.c +++ b/src/cmd/gc/racewalk.c @@ -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; } diff --git a/src/pkg/runtime/race/testdata/mop_test.go b/src/pkg/runtime/race/testdata/mop_test.go index 1a7ed96249..ae70cbb5f8 100644 --- a/src/pkg/runtime/race/testdata/mop_test.go +++ b/src/pkg/runtime/race/testdata/mop_test.go @@ -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 { diff --git a/src/pkg/runtime/race/testdata/slice_test.go b/src/pkg/runtime/race/testdata/slice_test.go index 1fe051b121..c85df5e3d6 100644 --- a/src/pkg/runtime/race/testdata/slice_test.go +++ b/src/pkg/runtime/race/testdata/slice_test.go @@ -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() {