mirror of
https://github.com/golang/go
synced 2024-11-23 05:20:11 -07:00
cmd/gc: implement more cases in racewalk.
Add missing CLOSUREVAR in switch. Mark MAKE, string conversion nodes as impossible. Control statements do not need instrumentation. Instrument COM and LROT nodes. Instrument map length. Update #4228 R=dvyukov, golang-dev CC=golang-dev https://golang.org/cl/7504047
This commit is contained in:
parent
76d5e2ce7d
commit
656bc3eb96
@ -196,6 +196,7 @@ racewalknode(Node **np, NodeList **init, int wr, int skip)
|
|||||||
case OPLUS:
|
case OPLUS:
|
||||||
case OREAL:
|
case OREAL:
|
||||||
case OIMAG:
|
case OIMAG:
|
||||||
|
case OCOM:
|
||||||
racewalknode(&n->left, init, wr, 0);
|
racewalknode(&n->left, init, wr, 0);
|
||||||
goto ret;
|
goto ret;
|
||||||
|
|
||||||
@ -222,23 +223,17 @@ racewalknode(Node **np, NodeList **init, int wr, int skip)
|
|||||||
case OCAP:
|
case OCAP:
|
||||||
racewalknode(&n->left, init, 0, 0);
|
racewalknode(&n->left, init, 0, 0);
|
||||||
if(istype(n->left->type, TMAP)) {
|
if(istype(n->left->type, TMAP)) {
|
||||||
// crashes on len(m[0]) or len(f())
|
n1 = nod(OCONVNOP, n->left, N);
|
||||||
SET(n1);
|
n1->type = ptrto(types[TUINT8]);
|
||||||
USED(n1);
|
|
||||||
/*
|
|
||||||
n1 = nod(OADDR, n->left, N);
|
|
||||||
n1 = conv(n1, types[TUNSAFEPTR]);
|
|
||||||
n1 = conv(n1, ptrto(ptrto(types[TINT8])));
|
|
||||||
n1 = nod(OIND, n1, N);
|
|
||||||
n1 = nod(OIND, n1, N);
|
n1 = nod(OIND, n1, N);
|
||||||
typecheck(&n1, Erv);
|
typecheck(&n1, Erv);
|
||||||
callinstr(&n1, init, 0, skip);
|
callinstr(&n1, init, 0, skip);
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
goto ret;
|
goto ret;
|
||||||
|
|
||||||
case OLSH:
|
case OLSH:
|
||||||
case ORSH:
|
case ORSH:
|
||||||
|
case OLROT:
|
||||||
case OAND:
|
case OAND:
|
||||||
case OANDNOT:
|
case OANDNOT:
|
||||||
case OOR:
|
case OOR:
|
||||||
@ -279,7 +274,6 @@ racewalknode(Node **np, NodeList **init, int wr, int skip)
|
|||||||
|
|
||||||
case ODIV:
|
case ODIV:
|
||||||
case OMOD:
|
case OMOD:
|
||||||
// TODO(dvyukov): add a test for this
|
|
||||||
racewalknode(&n->left, init, wr, 0);
|
racewalknode(&n->left, init, wr, 0);
|
||||||
racewalknode(&n->right, init, wr, 0);
|
racewalknode(&n->right, init, wr, 0);
|
||||||
goto ret;
|
goto ret;
|
||||||
@ -324,9 +318,30 @@ racewalknode(Node **np, NodeList **init, int wr, int skip)
|
|||||||
case OPANIC:
|
case OPANIC:
|
||||||
case ORECOVER:
|
case ORECOVER:
|
||||||
case OCONVIFACE:
|
case OCONVIFACE:
|
||||||
|
case OMAKECHAN:
|
||||||
|
case OMAKEMAP:
|
||||||
|
case OMAKESLICE:
|
||||||
|
case OCALL:
|
||||||
|
case OCOPY:
|
||||||
|
case ORUNESTR:
|
||||||
|
case OARRAYBYTESTR:
|
||||||
|
case OARRAYRUNESTR:
|
||||||
|
case OSTRARRAYBYTE:
|
||||||
|
case OSTRARRAYRUNE:
|
||||||
|
case OINDEXMAP: // lowered to call
|
||||||
|
case OCMPSTR:
|
||||||
|
case OADDSTR:
|
||||||
|
case ODOTTYPE:
|
||||||
|
case ODOTTYPE2:
|
||||||
yyerror("racewalk: %O must be lowered by now", n->op);
|
yyerror("racewalk: %O must be lowered by now", n->op);
|
||||||
goto ret;
|
goto ret;
|
||||||
|
|
||||||
|
// impossible nodes: only appear in backend.
|
||||||
|
case ORROTC:
|
||||||
|
case OEXTEND:
|
||||||
|
yyerror("racewalk: %O cannot exist now", n->op);
|
||||||
|
goto ret;
|
||||||
|
|
||||||
// just do generic traversal
|
// just do generic traversal
|
||||||
case OFOR:
|
case OFOR:
|
||||||
case OIF:
|
case OIF:
|
||||||
@ -334,43 +349,28 @@ racewalknode(Node **np, NodeList **init, int wr, int skip)
|
|||||||
case ORETURN:
|
case ORETURN:
|
||||||
case OSELECT:
|
case OSELECT:
|
||||||
case OEMPTY:
|
case OEMPTY:
|
||||||
|
case OBREAK:
|
||||||
|
case OCONTINUE:
|
||||||
|
case OFALL:
|
||||||
|
case OGOTO:
|
||||||
|
case OLABEL:
|
||||||
goto ret;
|
goto ret;
|
||||||
|
|
||||||
// does not require instrumentation
|
// does not require instrumentation
|
||||||
case OINDEXMAP: // implemented in runtime
|
|
||||||
case OPRINT: // don't bother instrumenting it
|
case OPRINT: // don't bother instrumenting it
|
||||||
case OPRINTN: // don't bother instrumenting it
|
case OPRINTN: // don't bother instrumenting it
|
||||||
case OPARAM: // it appears only in fn->exit to copy heap params back
|
case OPARAM: // it appears only in fn->exit to copy heap params back
|
||||||
goto ret;
|
goto ret;
|
||||||
|
|
||||||
// unimplemented
|
// unimplemented
|
||||||
case OCMPSTR:
|
|
||||||
case OADDSTR:
|
|
||||||
case OSLICESTR:
|
case OSLICESTR:
|
||||||
case OAPPEND:
|
case OAPPEND:
|
||||||
case OCOPY:
|
|
||||||
case OMAKECHAN:
|
|
||||||
case OMAKEMAP:
|
|
||||||
case OMAKESLICE:
|
|
||||||
case ORUNESTR:
|
|
||||||
case OARRAYBYTESTR:
|
|
||||||
case OARRAYRUNESTR:
|
|
||||||
case OSTRARRAYBYTE:
|
|
||||||
case OSTRARRAYRUNE:
|
|
||||||
case OCMPIFACE:
|
case OCMPIFACE:
|
||||||
case OARRAYLIT:
|
case OARRAYLIT:
|
||||||
case OMAPLIT:
|
case OMAPLIT:
|
||||||
case OSTRUCTLIT:
|
case OSTRUCTLIT:
|
||||||
case OCLOSURE:
|
case OCLOSURE:
|
||||||
case ODOTTYPE:
|
|
||||||
case ODOTTYPE2:
|
|
||||||
case OCALL:
|
|
||||||
case OBREAK:
|
|
||||||
case ODCL:
|
case ODCL:
|
||||||
case OCONTINUE:
|
|
||||||
case OFALL:
|
|
||||||
case OGOTO:
|
|
||||||
case OLABEL:
|
|
||||||
case ODCLCONST:
|
case ODCLCONST:
|
||||||
case ODCLTYPE:
|
case ODCLTYPE:
|
||||||
case OLITERAL:
|
case OLITERAL:
|
||||||
@ -378,14 +378,11 @@ racewalknode(Node **np, NodeList **init, int wr, int skip)
|
|||||||
case OTYPE:
|
case OTYPE:
|
||||||
case ONONAME:
|
case ONONAME:
|
||||||
case OINDREG:
|
case OINDREG:
|
||||||
case OCOM:
|
|
||||||
case ODOTMETH:
|
case ODOTMETH:
|
||||||
case OITAB:
|
case OITAB:
|
||||||
case OEXTEND:
|
|
||||||
case OHMUL:
|
case OHMUL:
|
||||||
case OLROT:
|
|
||||||
case ORROTC:
|
|
||||||
case OCHECKNOTNIL:
|
case OCHECKNOTNIL:
|
||||||
|
case OCLOSUREVAR:
|
||||||
goto ret;
|
goto ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
6
src/pkg/runtime/race/testdata/map_test.go
vendored
6
src/pkg/runtime/race/testdata/map_test.go
vendored
@ -94,8 +94,7 @@ func TestNoRaceMapRangeRange(t *testing.T) {
|
|||||||
<-ch
|
<-ch
|
||||||
}
|
}
|
||||||
|
|
||||||
// Map len is not instrumented.
|
func TestRaceMapLen(t *testing.T) {
|
||||||
func TestRaceFailingMapLen(t *testing.T) {
|
|
||||||
m := make(map[string]bool)
|
m := make(map[string]bool)
|
||||||
ch := make(chan bool, 1)
|
ch := make(chan bool, 1)
|
||||||
go func() {
|
go func() {
|
||||||
@ -117,8 +116,7 @@ func TestRaceMapDelete(t *testing.T) {
|
|||||||
<-ch
|
<-ch
|
||||||
}
|
}
|
||||||
|
|
||||||
// Map len is not instrumented.
|
func TestRaceMapLenDelete(t *testing.T) {
|
||||||
func TestRaceFailingMapLenDelete(t *testing.T) {
|
|
||||||
m := make(map[string]bool)
|
m := make(map[string]bool)
|
||||||
ch := make(chan bool, 1)
|
ch := make(chan bool, 1)
|
||||||
go func() {
|
go func() {
|
||||||
|
96
src/pkg/runtime/race/testdata/mop_test.go
vendored
96
src/pkg/runtime/race/testdata/mop_test.go
vendored
@ -306,6 +306,102 @@ func TestNoRacePlus(t *testing.T) {
|
|||||||
<-ch
|
<-ch
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestRaceComplement(t *testing.T) {
|
||||||
|
var x, y, z int
|
||||||
|
ch := make(chan int, 2)
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
x = ^y
|
||||||
|
ch <- 1
|
||||||
|
}()
|
||||||
|
go func() {
|
||||||
|
y = ^z
|
||||||
|
ch <- 1
|
||||||
|
}()
|
||||||
|
<-ch
|
||||||
|
<-ch
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRaceDiv(t *testing.T) {
|
||||||
|
var x, y, z int
|
||||||
|
ch := make(chan int, 2)
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
x = y / (z + 1)
|
||||||
|
ch <- 1
|
||||||
|
}()
|
||||||
|
go func() {
|
||||||
|
y = z
|
||||||
|
ch <- 1
|
||||||
|
}()
|
||||||
|
<-ch
|
||||||
|
<-ch
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRaceDivConst(t *testing.T) {
|
||||||
|
var x, y, z int
|
||||||
|
ch := make(chan int, 2)
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
x = y / 3
|
||||||
|
ch <- 1
|
||||||
|
}()
|
||||||
|
go func() {
|
||||||
|
y = z
|
||||||
|
ch <- 1
|
||||||
|
}()
|
||||||
|
<-ch
|
||||||
|
<-ch
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRaceMod(t *testing.T) {
|
||||||
|
var x, y, z int
|
||||||
|
ch := make(chan int, 2)
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
x = y % (z + 1)
|
||||||
|
ch <- 1
|
||||||
|
}()
|
||||||
|
go func() {
|
||||||
|
y = z
|
||||||
|
ch <- 1
|
||||||
|
}()
|
||||||
|
<-ch
|
||||||
|
<-ch
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRaceModConst(t *testing.T) {
|
||||||
|
var x, y, z int
|
||||||
|
ch := make(chan int, 2)
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
x = y % 3
|
||||||
|
ch <- 1
|
||||||
|
}()
|
||||||
|
go func() {
|
||||||
|
y = z
|
||||||
|
ch <- 1
|
||||||
|
}()
|
||||||
|
<-ch
|
||||||
|
<-ch
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRaceRotate(t *testing.T) {
|
||||||
|
var x, y, z uint32
|
||||||
|
ch := make(chan int, 2)
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
x = y<<12 | y>>20
|
||||||
|
ch <- 1
|
||||||
|
}()
|
||||||
|
go func() {
|
||||||
|
y = z
|
||||||
|
ch <- 1
|
||||||
|
}()
|
||||||
|
<-ch
|
||||||
|
<-ch
|
||||||
|
}
|
||||||
|
|
||||||
// May crash if the instrumentation is reckless.
|
// May crash if the instrumentation is reckless.
|
||||||
func TestNoRaceEnoughRegisters(t *testing.T) {
|
func TestNoRaceEnoughRegisters(t *testing.T) {
|
||||||
// from erf.go
|
// from erf.go
|
||||||
|
12
src/pkg/runtime/race/testdata/regression_test.go
vendored
12
src/pkg/runtime/race/testdata/regression_test.go
vendored
@ -45,6 +45,18 @@ func InstrumentMapLen3() {
|
|||||||
_ = len(*m[0])
|
_ = len(*m[0])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestRaceUnaddressableMapLen(t *testing.T) {
|
||||||
|
m := make(map[int]map[int]int)
|
||||||
|
ch := make(chan int, 1)
|
||||||
|
m[0] = make(map[int]int)
|
||||||
|
go func() {
|
||||||
|
_ = len(m[0])
|
||||||
|
ch <- 0
|
||||||
|
}()
|
||||||
|
m[0][0] = 1
|
||||||
|
<-ch
|
||||||
|
}
|
||||||
|
|
||||||
type Rect struct {
|
type Rect struct {
|
||||||
x, y int
|
x, y int
|
||||||
}
|
}
|
||||||
|
21
src/pkg/runtime/race/testdata/slice_test.go
vendored
21
src/pkg/runtime/race/testdata/slice_test.go
vendored
@ -463,3 +463,24 @@ func TestRaceSliceRuneToString(t *testing.T) {
|
|||||||
s[9] = 42
|
s[9] = 42
|
||||||
<-c
|
<-c
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestRaceConcatString(t *testing.T) {
|
||||||
|
s := "hello"
|
||||||
|
c := make(chan string, 1)
|
||||||
|
go func() {
|
||||||
|
c <- s + " world"
|
||||||
|
}()
|
||||||
|
s = "world"
|
||||||
|
<-c
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRaceCompareString(t *testing.T) {
|
||||||
|
s1 := "hello"
|
||||||
|
s2 := "world"
|
||||||
|
c := make(chan bool, 1)
|
||||||
|
go func() {
|
||||||
|
c <- s1 == s2
|
||||||
|
}()
|
||||||
|
s1 = s2
|
||||||
|
<-c
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user