mirror of
				https://github.com/golang/go.git
				synced 2025-11-04 02:30:57 +00:00 
			
		
		
		
	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 <khr@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Matthew Dempsky <mdempsky@google.com>
		
			
				
	
	
		
			63 lines
		
	
	
	
		
			1.6 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			63 lines
		
	
	
	
		
			1.6 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
// 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))
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
}
 |