Skip to content

Commit 14bdcc7

Browse files
committed
cmd/compile: fix racewalk{enter,exit} removal
We can't remove race instrumentation unless there are no calls, not just no static calls. Closure and interface calls also count. The problem in issue 29329 is that there was a racefuncenter, an InterCall, and a racefuncexit. The racefuncenter was removed, then the InterCall was rewritten to a StaticCall. That prevented the racefuncexit from being removed. That caused an imbalance in racefuncenter/racefuncexit calls, which made the race detector barf. Bug introduced at CL 121235 Fixes #29329 Change-Id: I2c94ac6cf918dd910b74b2a0de5dc2480d236f16 Reviewed-on: https://go-review.googlesource.com/c/155917 Run-TryBot: Keith Randall <[email protected]> TryBot-Result: Gobot Gobot <[email protected]> Reviewed-by: Brad Fitzpatrick <[email protected]>
1 parent d459962 commit 14bdcc7

File tree

2 files changed

+111
-1
lines changed

2 files changed

+111
-1
lines changed

src/cmd/compile/internal/ssa/rewrite.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1111,7 +1111,8 @@ func needRaceCleanup(sym interface{}, v *Value) bool {
11111111
}
11121112
for _, b := range f.Blocks {
11131113
for _, v := range b.Values {
1114-
if v.Op == OpStaticCall {
1114+
switch v.Op {
1115+
case OpStaticCall:
11151116
switch v.Aux.(fmt.Stringer).String() {
11161117
case "runtime.racefuncenter", "runtime.racefuncexit", "runtime.panicindex",
11171118
"runtime.panicslice", "runtime.panicdivide", "runtime.panicwrap":
@@ -1122,6 +1123,9 @@ func needRaceCleanup(sym interface{}, v *Value) bool {
11221123
// for accurate stacktraces.
11231124
return false
11241125
}
1126+
case OpClosureCall, OpInterCall:
1127+
// We must keep the race functions if there are any other call types.
1128+
return false
11251129
}
11261130
}
11271131
}

test/fixedbugs/issue29329.go

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
// run -race
2+
3+
// Copyright 2018 The Go Authors. All rights reserved.
4+
// Use of this source code is governed by a BSD-style
5+
// license that can be found in the LICENSE file.
6+
7+
// +build linux,amd64
8+
9+
package main
10+
11+
import (
12+
"fmt"
13+
)
14+
15+
type LineString []Point
16+
type Point [2]float64
17+
18+
//go:noinline
19+
func benchmarkData() LineString {
20+
return LineString{{1.0, 2.0}}
21+
}
22+
23+
func (ls LineString) Clone() LineString {
24+
ps := MultiPoint(ls)
25+
return LineString(ps.Clone())
26+
}
27+
28+
type MultiPoint []Point
29+
30+
func (mp MultiPoint) Clone() MultiPoint {
31+
if mp == nil {
32+
return nil
33+
}
34+
35+
points := make([]Point, len(mp))
36+
copy(points, mp)
37+
38+
return MultiPoint(points)
39+
}
40+
41+
func F1() {
42+
cases := []struct {
43+
threshold float64
44+
length int
45+
}{
46+
{0.1, 1118},
47+
{0.5, 257},
48+
{1.0, 144},
49+
{1.5, 95},
50+
{2.0, 71},
51+
{3.0, 46},
52+
{4.0, 39},
53+
{5.0, 33},
54+
}
55+
56+
ls := benchmarkData()
57+
58+
for k := 0; k < 100; k++ {
59+
for i, tc := range cases {
60+
r := DouglasPeucker(tc.threshold).LineString(ls.Clone())
61+
if len(r) == tc.length {
62+
fmt.Printf("%d: unexpected\n", i)
63+
}
64+
}
65+
}
66+
}
67+
68+
// A DouglasPeuckerSimplifier wraps the DouglasPeucker function.
69+
type DouglasPeuckerSimplifier struct {
70+
Threshold float64
71+
}
72+
73+
// DouglasPeucker creates a new DouglasPeuckerSimplifier.
74+
func DouglasPeucker(threshold float64) *DouglasPeuckerSimplifier {
75+
return &DouglasPeuckerSimplifier{
76+
Threshold: threshold,
77+
}
78+
}
79+
80+
func (s *DouglasPeuckerSimplifier) LineString(ls LineString) LineString {
81+
return lineString(s, ls)
82+
}
83+
84+
type simplifier interface {
85+
simplify(LineString, bool) (LineString, []int)
86+
}
87+
88+
func lineString(s simplifier, ls LineString) LineString {
89+
return runSimplify(s, ls)
90+
}
91+
92+
func runSimplify(s simplifier, ls LineString) LineString {
93+
if len(ls) <= 2 {
94+
return ls
95+
}
96+
ls, _ = s.simplify(ls, false)
97+
return ls
98+
}
99+
100+
func (s *DouglasPeuckerSimplifier) simplify(ls LineString, wim bool) (LineString, []int) {
101+
return nil, nil
102+
}
103+
104+
func main() {
105+
F1()
106+
}

0 commit comments

Comments
 (0)