Commit 14bdcc76 authored by Keith Randall's avatar Keith Randall Committed by Keith Randall

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 <khr@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: 's avatarBrad Fitzpatrick <bradfitz@golang.org>
parent d4599629
...@@ -1111,7 +1111,8 @@ func needRaceCleanup(sym interface{}, v *Value) bool { ...@@ -1111,7 +1111,8 @@ func needRaceCleanup(sym interface{}, v *Value) bool {
} }
for _, b := range f.Blocks { for _, b := range f.Blocks {
for _, v := range b.Values { for _, v := range b.Values {
if v.Op == OpStaticCall { switch v.Op {
case OpStaticCall:
switch v.Aux.(fmt.Stringer).String() { switch v.Aux.(fmt.Stringer).String() {
case "runtime.racefuncenter", "runtime.racefuncexit", "runtime.panicindex", case "runtime.racefuncenter", "runtime.racefuncexit", "runtime.panicindex",
"runtime.panicslice", "runtime.panicdivide", "runtime.panicwrap": "runtime.panicslice", "runtime.panicdivide", "runtime.panicwrap":
...@@ -1122,6 +1123,9 @@ func needRaceCleanup(sym interface{}, v *Value) bool { ...@@ -1122,6 +1123,9 @@ func needRaceCleanup(sym interface{}, v *Value) bool {
// for accurate stacktraces. // for accurate stacktraces.
return false return false
} }
case OpClosureCall, OpInterCall:
// We must keep the race functions if there are any other call types.
return false
} }
} }
} }
......
// run -race
// Copyright 2018 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build linux,amd64
package main
import (
"fmt"
)
type LineString []Point
type Point [2]float64
//go:noinline
func benchmarkData() LineString {
return LineString{{1.0, 2.0}}
}
func (ls LineString) Clone() LineString {
ps := MultiPoint(ls)
return LineString(ps.Clone())
}
type MultiPoint []Point
func (mp MultiPoint) Clone() MultiPoint {
if mp == nil {
return nil
}
points := make([]Point, len(mp))
copy(points, mp)
return MultiPoint(points)
}
func F1() {
cases := []struct {
threshold float64
length int
}{
{0.1, 1118},
{0.5, 257},
{1.0, 144},
{1.5, 95},
{2.0, 71},
{3.0, 46},
{4.0, 39},
{5.0, 33},
}
ls := benchmarkData()
for k := 0; k < 100; k++ {
for i, tc := range cases {
r := DouglasPeucker(tc.threshold).LineString(ls.Clone())
if len(r) == tc.length {
fmt.Printf("%d: unexpected\n", i)
}
}
}
}
// A DouglasPeuckerSimplifier wraps the DouglasPeucker function.
type DouglasPeuckerSimplifier struct {
Threshold float64
}
// DouglasPeucker creates a new DouglasPeuckerSimplifier.
func DouglasPeucker(threshold float64) *DouglasPeuckerSimplifier {
return &DouglasPeuckerSimplifier{
Threshold: threshold,
}
}
func (s *DouglasPeuckerSimplifier) LineString(ls LineString) LineString {
return lineString(s, ls)
}
type simplifier interface {
simplify(LineString, bool) (LineString, []int)
}
func lineString(s simplifier, ls LineString) LineString {
return runSimplify(s, ls)
}
func runSimplify(s simplifier, ls LineString) LineString {
if len(ls) <= 2 {
return ls
}
ls, _ = s.simplify(ls, false)
return ls
}
func (s *DouglasPeuckerSimplifier) simplify(ls LineString, wim bool) (LineString, []int) {
return nil, nil
}
func main() {
F1()
}
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