]> Cypherpunks.ru repositories - gostls13.git/commitdiff
sort: simplify bootstrap
authorRuss Cox <rsc@golang.org>
Tue, 30 Apr 2019 19:23:14 +0000 (15:23 -0400)
committerBrad Fitzpatrick <bradfitz@golang.org>
Thu, 2 May 2019 20:30:31 +0000 (20:30 +0000)
We compile package sort as part of the compiler bootstrap,
to make sure the compiler uses a consistent sort algorithm
no matter what version of Go it is compiled against.
(This matters for elements that compare "equal" but are distinguishable.)

Package sort was compiled in such a way as to disallow
sort.Slice entirely during bootstrap (at least with some compilers),
while cmd/internal/obj was compiled in such a way as to
make obj.SortSlice available to all compilers, precisely because
sort.Slice was not. This is all highly confusing.
Simplify by making sort.Slice available all the time.

Followup to CL 169137 and #30440
(and also CL 40114 and CL 73951).

Change-Id: I127f4e02d6c71392805d256c3a90ef7c51f9ba0c
Reviewed-on: https://go-review.googlesource.com/c/go/+/174525
Run-TryBot: Russ Cox <rsc@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
13 files changed:
src/cmd/compile/internal/gc/iexport.go
src/cmd/compile/internal/gc/main.go
src/cmd/compile/internal/gc/obj.go
src/cmd/compile/internal/gc/pgen.go
src/cmd/compile/internal/types/sym_test.go
src/cmd/internal/obj/bootstrap.go [deleted file]
src/cmd/internal/obj/objfile.go
src/go/build/deps_test.go
src/sort/slice.go
src/sort/slice_go113.go [new file with mode: 0644]
src/sort/slice_go14.go [new file with mode: 0644]
src/sort/slice_go18.go [moved from src/cmd/internal/obj/sort.go with 55% similarity]
src/sort/slice_pre113.go [deleted file]

index 93099bfe3d1c64bce116fc8c86894432b46ec114..560aeabf76d4cf3df26e284f5ea51e2e76df65e2 100644 (file)
@@ -202,12 +202,12 @@ import (
        "bufio"
        "bytes"
        "cmd/compile/internal/types"
-       "cmd/internal/obj"
        "cmd/internal/src"
        "encoding/binary"
        "fmt"
        "io"
        "math/big"
+       "sort"
        "strings"
 )
 
@@ -321,12 +321,12 @@ func (w *exportWriter) writeIndex(index map[*Node]uint64, mainIndex bool) {
        for pkg, objs := range pkgObjs {
                pkgs = append(pkgs, pkg)
 
-               obj.SortSlice(objs, func(i, j int) bool {
+               sort.Slice(objs, func(i, j int) bool {
                        return objs[i].Sym.Name < objs[j].Sym.Name
                })
        }
 
-       obj.SortSlice(pkgs, func(i, j int) bool {
+       sort.Slice(pkgs, func(i, j int) bool {
                return pkgs[i].Path < pkgs[j].Path
        })
 
index dc3fb64e274b4123fdeb20a1b356724bf4e0b766..51b60fb417b67b3c4e333cd1dc398c97ee61b313 100644 (file)
@@ -27,6 +27,7 @@ import (
        "path"
        "regexp"
        "runtime"
+       "sort"
        "strconv"
        "strings"
 )
@@ -723,7 +724,7 @@ func Main(archInit func(*Arch)) {
        }
 
        // Check whether any of the functions we have compiled have gigantic stack frames.
-       obj.SortSlice(largeStackFrames, func(i, j int) bool {
+       sort.Slice(largeStackFrames, func(i, j int) bool {
                return largeStackFrames[i].pos.Before(largeStackFrames[j].pos)
        })
        for _, large := range largeStackFrames {
@@ -1313,7 +1314,7 @@ func clearImports() {
                }
        }
 
-       obj.SortSlice(unused, func(i, j int) bool { return unused[i].pos.Before(unused[j].pos) })
+       sort.Slice(unused, func(i, j int) bool { return unused[i].pos.Before(unused[j].pos) })
        for _, pkg := range unused {
                pkgnotused(pkg.pos, pkg.path, pkg.name)
        }
index 86d52f50846e731a28aa841c1226bd983fb3861e..d0ba6ffb75ef2f64aadd6b0ce8ba6613e6fbf12e 100644 (file)
@@ -14,6 +14,7 @@ import (
        "encoding/json"
        "fmt"
        "io"
+       "sort"
        "strconv"
 )
 
@@ -259,7 +260,7 @@ func dumpglobls() {
                }
        }
 
-       obj.SortSlice(funcsyms, func(i, j int) bool {
+       sort.Slice(funcsyms, func(i, j int) bool {
                return funcsyms[i].LinksymName() < funcsyms[j].LinksymName()
        })
        for _, s := range funcsyms {
index 8e4126d7799f243f549a9dad16d8a35807b4cca7..2ae7452e7db11824c0553a603e36aab56101e436 100644 (file)
@@ -348,7 +348,7 @@ func compileFunctions() {
                        // Compile the longest functions first,
                        // since they're most likely to be the slowest.
                        // This helps avoid stragglers.
-                       obj.SortSlice(compilequeue, func(i, j int) bool {
+                       sort.Slice(compilequeue, func(i, j int) bool {
                                return compilequeue[i].Nbody.Len() > compilequeue[j].Nbody.Len()
                        })
                }
index a2bb02deda3c6ab29d0e24de38c0c04bab9202e9..94efd42aa4ad446592c4e22706b8ce2545314eeb 100644 (file)
@@ -6,8 +6,8 @@ package types_test
 
 import (
        "cmd/compile/internal/types"
-       "cmd/internal/obj"
        "reflect"
+       "sort"
        "testing"
 )
 
@@ -50,7 +50,7 @@ func TestSymLess(t *testing.T) {
        if reflect.DeepEqual(data, want) {
                t.Fatal("data must be shuffled")
        }
-       obj.SortSlice(data, func(i, j int) bool { return data[i].Less(data[j]) })
+       sort.Slice(data, func(i, j int) bool { return data[i].Less(data[j]) })
        if !reflect.DeepEqual(data, want) {
                t.Logf("want: %#v", want)
                t.Logf("data: %#v", data)
diff --git a/src/cmd/internal/obj/bootstrap.go b/src/cmd/internal/obj/bootstrap.go
deleted file mode 100644 (file)
index 42835e1..0000000
+++ /dev/null
@@ -1,34 +0,0 @@
-// 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)
-}
index a7927f50b73583306780099353ef7375218fb46d..6921df3675e76575141fdab5da396dcbb737c119 100644 (file)
@@ -104,7 +104,7 @@ func WriteObjFile(ctxt *Link, b *bufio.Writer) {
                // As they are created during Progedit, two symbols can be switched between
                // two different compilations. Therefore, BuildID will be different.
                // TODO: find a better place and optimize to only sort TOC symbols
-               SortSlice(ctxt.Data, func(i, j int) bool {
+               sort.Slice(ctxt.Data, func(i, j int) bool {
                        return ctxt.Data[i].Name < ctxt.Data[j].Name
                })
        }
index 50650bd37396b8cb876811dd6fc83637096bd3a0..f38f13a6f2947d355499ed97faa135bef68e5640 100644 (file)
@@ -586,9 +586,8 @@ func findImports(pkg string) ([]string, error) {
        var haveImport = map[string]bool{}
        for _, file := range files {
                name := file.Name()
-               if name == "slice_pre113.go" {
-                       // This file is ignored by build tags which aren't
-                       // handled by this findImports func.
+               if name == "slice_go14.go" || name == "slice_go18.go" {
+                       // These files are for compiler bootstrap with older versions of Go and not built in the standard build.
                        continue
                }
                if !strings.HasSuffix(name, ".go") || strings.HasSuffix(name, "_test.go") {
index 5196affcfd3fcc961f80e49e2e492816c28bdb59..1f42c2a3fdc20318a582620274e3d7ee4050522b 100644 (file)
@@ -2,14 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// +build !compiler_bootstrap go1.13
-
 package sort
 
-import (
-       "internal/reflectlite"
-)
-
 // Slice sorts the provided slice given the provided less function.
 //
 // The sort is not guaranteed to be stable. For a stable sort, use
@@ -17,8 +11,8 @@ import (
 //
 // The function panics if the provided interface is not a slice.
 func Slice(slice interface{}, less func(i, j int) bool) {
-       rv := reflectlite.ValueOf(slice)
-       swap := reflectlite.Swapper(slice)
+       rv := reflectValueOf(slice)
+       swap := reflectSwapper(slice)
        length := rv.Len()
        quickSort_func(lessSwap{less, swap}, 0, length, maxDepth(length))
 }
@@ -28,8 +22,8 @@ func Slice(slice interface{}, less func(i, j int) bool) {
 //
 // The function panics if the provided interface is not a slice.
 func SliceStable(slice interface{}, less func(i, j int) bool) {
-       rv := reflectlite.ValueOf(slice)
-       swap := reflectlite.Swapper(slice)
+       rv := reflectValueOf(slice)
+       swap := reflectSwapper(slice)
        stable_func(lessSwap{less, swap}, rv.Len())
 }
 
@@ -37,7 +31,7 @@ func SliceStable(slice interface{}, less func(i, j int) bool) {
 //
 // The function panics if the provided interface is not a slice.
 func SliceIsSorted(slice interface{}, less func(i, j int) bool) bool {
-       rv := reflectlite.ValueOf(slice)
+       rv := reflectValueOf(slice)
        n := rv.Len()
        for i := n - 1; i > 0; i-- {
                if less(i, i-1) {
diff --git a/src/sort/slice_go113.go b/src/sort/slice_go113.go
new file mode 100644 (file)
index 0000000..bf24db7
--- /dev/null
@@ -0,0 +1,12 @@
+// 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.13
+
+package sort
+
+import "internal/reflectlite"
+
+var reflectValueOf = reflectlite.ValueOf
+var reflectSwapper = reflectlite.Swapper
diff --git a/src/sort/slice_go14.go b/src/sort/slice_go14.go
new file mode 100644 (file)
index 0000000..3bf5cbc
--- /dev/null
@@ -0,0 +1,22 @@
+// 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 sort
+
+import "reflect"
+
+var reflectValueOf = reflect.ValueOf
+
+func reflectSwapper(x interface{}) func(int, int) {
+       v := reflectValueOf(x)
+       tmp := reflect.New(v.Type().Elem()).Elem()
+       return func(i, j int) {
+               a, b := v.Index(i), v.Index(j)
+               tmp.Set(a)
+               a.Set(b)
+               b.Set(tmp)
+       }
+}
similarity index 55%
rename from src/cmd/internal/obj/sort.go
rename to src/sort/slice_go18.go
index 0cb801ee9803a5cb826d7ac25761bc857585c7ad..e1766040a78a567736c1a202593b84624cff3756 100644 (file)
@@ -2,12 +2,11 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// +build go1.8
+// +build go1.8,!go1.13
 
-package obj
+package sort
 
-import "sort"
+import "reflect"
 
-func SortSlice(slice interface{}, less func(i, j int) bool) {
-       sort.Slice(slice, less)
-}
+var reflectValueOf = reflect.ValueOf
+var reflectSwapper = reflect.Swapper
diff --git a/src/sort/slice_pre113.go b/src/sort/slice_pre113.go
deleted file mode 100644 (file)
index 4d5f759..0000000
+++ /dev/null
@@ -1,46 +0,0 @@
-// 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,!go1.13
-
-package sort
-
-import "reflect"
-
-// Slice sorts the provided slice given the provided less function.
-//
-// The sort is not guaranteed to be stable. For a stable sort, use
-// SliceStable.
-//
-// The function panics if the provided interface is not a slice.
-func Slice(slice interface{}, less func(i, j int) bool) {
-       rv := reflect.ValueOf(slice)
-       swap := reflect.Swapper(slice)
-       length := rv.Len()
-       quickSort_func(lessSwap{less, swap}, 0, length, maxDepth(length))
-}
-
-// SliceStable sorts the provided slice given the provided less
-// function while keeping the original order of equal elements.
-//
-// The function panics if the provided interface is not a slice.
-func SliceStable(slice interface{}, less func(i, j int) bool) {
-       rv := reflect.ValueOf(slice)
-       swap := reflect.Swapper(slice)
-       stable_func(lessSwap{less, swap}, rv.Len())
-}
-
-// SliceIsSorted tests whether a slice is sorted.
-//
-// The function panics if the provided interface is not a slice.
-func SliceIsSorted(slice interface{}, less func(i, j int) bool) bool {
-       rv := reflect.ValueOf(slice)
-       n := rv.Len()
-       for i := n - 1; i > 0; i-- {
-               if less(i, i-1) {
-                       return false
-               }
-       }
-       return true
-}