Commit 826a09cd authored by Josh Bleecher Snyder's avatar Josh Bleecher Snyder

cmd/internal/obj: add SortSlice

sort.Slice was added in Go 1.8.
It's nice to use, and faster than sort.Sort,
so it'd be nice to be able to use it in the toolchain.
This CL adds obj.SortSlice, which is sort.Slice,
but with a slower fallback version for bootstrapping.

This CL also includes a single demo+test use.

Change-Id: I2accc60b61f8e48c8ab4f1a63473e3b87af9b691
Reviewed-on: https://go-review.googlesource.com/40114
Run-TryBot: Josh Bleecher Snyder <josharian@gmail.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: 's avatarBrad Fitzpatrick <bradfitz@golang.org>
parent d6dd7ce1
...@@ -49,16 +49,7 @@ type Sig struct { ...@@ -49,16 +49,7 @@ type Sig struct {
offset int32 offset int32
} }
// byMethodNameAndPackagePath sorts method signatures by name, then package path. // siglt sorts method signatures by name, then package path.
type byMethodNameAndPackagePath []*Sig
func (x byMethodNameAndPackagePath) Len() int { return len(x) }
func (x byMethodNameAndPackagePath) Swap(i, j int) { x[i], x[j] = x[j], x[i] }
func (x byMethodNameAndPackagePath) Less(i, j int) bool {
return siglt(x[i], x[j])
}
// siglt reports whether a < b
func siglt(a, b *Sig) bool { func siglt(a, b *Sig) bool {
if a.name != b.name { if a.name != b.name {
return a.name < b.name return a.name < b.name
...@@ -382,7 +373,7 @@ func methods(t *types.Type) []*Sig { ...@@ -382,7 +373,7 @@ func methods(t *types.Type) []*Sig {
} }
} }
sort.Sort(byMethodNameAndPackagePath(ms)) obj.SortSlice(ms, func(i, j int) bool { return siglt(ms[i], ms[j]) })
return ms return ms
} }
......
...@@ -6,12 +6,12 @@ package gc ...@@ -6,12 +6,12 @@ package gc
import ( import (
"cmd/compile/internal/types" "cmd/compile/internal/types"
"cmd/internal/obj"
"reflect" "reflect"
"sort"
"testing" "testing"
) )
func TestSortingByMethodNameAndPackagePath(t *testing.T) { func TestSortingBySigLT(t *testing.T) {
data := []*Sig{ data := []*Sig{
&Sig{name: "b", pkg: &types.Pkg{Path: "abc"}}, &Sig{name: "b", pkg: &types.Pkg{Path: "abc"}},
&Sig{name: "b", pkg: nil}, &Sig{name: "b", pkg: nil},
...@@ -38,11 +38,10 @@ func TestSortingByMethodNameAndPackagePath(t *testing.T) { ...@@ -38,11 +38,10 @@ func TestSortingByMethodNameAndPackagePath(t *testing.T) {
if reflect.DeepEqual(data, want) { if reflect.DeepEqual(data, want) {
t.Fatal("data must be shuffled") t.Fatal("data must be shuffled")
} }
sort.Sort(byMethodNameAndPackagePath(data)) obj.SortSlice(data, func(i, j int) bool { return siglt(data[i], data[j]) })
if !reflect.DeepEqual(data, want) { if !reflect.DeepEqual(data, want) {
t.Logf("want: %#v", want) t.Logf("want: %#v", want)
t.Logf("data: %#v", data) t.Logf("data: %#v", data)
t.Errorf("sorting failed") t.Errorf("sorting failed")
} }
} }
// Copyright 2017 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 !go1.8
package obj
import (
"reflect"
"sort"
)
func SortSlice(slice interface{}, less func(i, j int) bool) {
val := reflect.ValueOf(slice)
tmp := reflect.New(val.Type().Elem()).Elem()
x := sliceByFn{val: val, tmp: tmp, less: less}
sort.Sort(x)
}
type sliceByFn struct {
val reflect.Value
tmp reflect.Value
less func(i, j int) bool
}
func (x sliceByFn) Len() int { return x.val.Len() }
func (x sliceByFn) Less(i, j int) bool { return x.less(i, j) }
func (x sliceByFn) Swap(i, j int) {
a, b := x.val.Index(i), x.val.Index(j)
x.tmp.Set(a)
a.Set(b)
b.Set(x.tmp)
}
// Copyright 2017 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 go1.8
package obj
import "sort"
func SortSlice(slice interface{}, less func(i, j int) bool) {
sort.Slice(slice, less)
}
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