-
Notifications
You must be signed in to change notification settings - Fork 17.8k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
cmd/compile: clean up equality generation
We're using sort.SliceStable, so no need to keep track of indexes as well. Use a more robust test for whether a node is a call. Add a test that we're actually reordering comparisons. This test fails without the alg.go changes in this CL because eqstring uses OCALLFUNC instead of OCALL for its data comparisons. Update #8606 Change-Id: Ieeec33434c72e3aa328deb11cc415cfda05632e2 Reviewed-on: https://go-review.googlesource.com/c/go/+/237921 Run-TryBot: Keith Randall <[email protected]> TryBot-Result: Gobot Gobot <[email protected]> Reviewed-by: Matthew Dempsky <[email protected]>
- Loading branch information
Showing
2 changed files
with
75 additions
and
19 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
// run | ||
|
||
// Copyright 2020 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. | ||
|
||
// This is an optimization check. We want to make sure that we compare | ||
// string lengths, and other scalar fields, before checking string | ||
// contents. There's no way to verify this in the language, and | ||
// codegen tests in test/codegen can't really detect ordering | ||
// optimizations like this. Instead, we generate invalid strings with | ||
// bad backing store pointers but nonzero length, so we can check that | ||
// the backing store never gets compared. | ||
// | ||
// We use two different bad strings so that pointer comparisons of | ||
// backing store pointers fail. | ||
|
||
package main | ||
|
||
import ( | ||
"fmt" | ||
"reflect" | ||
"unsafe" | ||
) | ||
|
||
func bad1() string { | ||
s := "foo" | ||
(*reflect.StringHeader)(unsafe.Pointer(&s)).Data = 1 // write bad value to data ptr | ||
return s | ||
} | ||
func bad2() string { | ||
s := "foo" | ||
(*reflect.StringHeader)(unsafe.Pointer(&s)).Data = 2 // write bad value to data ptr | ||
return s | ||
} | ||
|
||
type SI struct { | ||
s string | ||
i int | ||
} | ||
|
||
type SS struct { | ||
s string | ||
t string | ||
} | ||
|
||
func main() { | ||
for _, test := range []struct { | ||
a, b interface{} | ||
}{ | ||
{SI{s: bad1(), i: 1}, SI{s: bad2(), i: 2}}, | ||
{SS{s: bad1(), t: "a"}, SS{s: bad2(), t: "aa"}}, | ||
{SS{s: "a", t: bad1()}, SS{s: "b", t: bad2()}}, | ||
// This one would panic because the length of both strings match, and we check | ||
// the body of the bad strings before the body of the good strings. | ||
//{SS{s: bad1(), t: "a"}, SS{s: bad2(), t: "b"}}, | ||
} { | ||
if test.a == test.b { | ||
panic(fmt.Sprintf("values %#v and %#v should not be equal", test.a, test.b)) | ||
} | ||
} | ||
|
||
} |