]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/compile, runtime: eliminate growslice_n
authorMatthew Dempsky <mdempsky@google.com>
Sun, 13 Mar 2016 22:22:45 +0000 (15:22 -0700)
committerMatthew Dempsky <mdempsky@google.com>
Sun, 13 Mar 2016 23:34:31 +0000 (23:34 +0000)
Fixes #11419.

Change-Id: I7935a253e3e96191a33f5041bab203ecc5f0c976
Reviewed-on: https://go-review.googlesource.com/20647
Reviewed-by: Keith Randall <khr@golang.org>
src/cmd/compile/internal/gc/builtin.go
src/cmd/compile/internal/gc/builtin/runtime.go
src/cmd/compile/internal/gc/walk.go
src/runtime/slice.go

index 4a6e56fe47255232db3bdfc4cd9830fe29a303b2..6ca870285aff4ff90fcb984a54a6b221f6318c69 100644 (file)
@@ -128,7 +128,6 @@ const runtimeimport = "" +
        "func @\"\".block ()\n" +
        "func @\"\".makeslice (@\"\".typ·2 *byte, @\"\".nel·3 int64, @\"\".cap·4 int64) (@\"\".ary·1 []any)\n" +
        "func @\"\".growslice (@\"\".typ·2 *byte, @\"\".old·3 []any, @\"\".cap·4 int) (@\"\".ary·1 []any)\n" +
-       "func @\"\".growslice_n (@\"\".typ·2 *byte, @\"\".old·3 []any, @\"\".n·4 int) (@\"\".ary·1 []any)\n" +
        "func @\"\".memmove (@\"\".to·1 *any, @\"\".frm·2 *any, @\"\".length·3 uintptr \"unsafe-uintptr\")\n" +
        "func @\"\".memclr (@\"\".ptr·1 *byte, @\"\".length·2 uintptr \"unsafe-uintptr\")\n" +
        "func @\"\".memequal (@\"\".x·2 *any, @\"\".y·3 *any, @\"\".size·4 uintptr \"unsafe-uintptr\") (? bool)\n" +
index 4286f361b82f490a764f61df3d98cf4f1464f1c4..944cac2c635dcc5c51ea4e9715552b0a18d06ce4 100644 (file)
@@ -165,7 +165,6 @@ func block()
 
 func makeslice(typ *byte, nel int64, cap int64) (ary []any)
 func growslice(typ *byte, old []any, cap int) (ary []any)
-func growslice_n(typ *byte, old []any, n int) (ary []any)
 func memmove(to *any, frm *any, length uintptr)
 func memclr(ptr *byte, length uintptr)
 
index fe9b0e5dc767d5b284294e0553ea83663e985725..afc560d5d0ad64c3cb611ce32087568cee55ed89 100644 (file)
@@ -2777,10 +2777,12 @@ func addstr(n *Node, init *Nodes) *Node {
 // expand append(l1, l2...) to
 //   init {
 //     s := l1
-//     if n := len(l1) + len(l2) - cap(s); n > 0 {
-//       s = growslice_n(s, n)
+//     n := len(s) + len(l2)
+//     // Compare as uint so growslice can panic on overflow.
+//     if uint(n) > uint(cap(s)) {
+//       s = growslice(s, n)
 //     }
-//     s = s[:len(l1)+len(l2)]
+//     s = s[:n]
 //     memmove(&s[len(l1)], &l2[0], len(l2)*sizeof(T))
 //   }
 //   s
@@ -2800,33 +2802,38 @@ func appendslice(n *Node, init *Nodes) *Node {
        l1 := n.List.First()
        l2 := n.List.Second()
 
-       s := temp(l1.Type) // var s []T
        var l []*Node
+
+       // var s []T
+       s := temp(l1.Type)
        l = append(l, Nod(OAS, s, l1)) // s = l1
 
-       nt := temp(Types[TINT])
+       // n := len(s) + len(l2)
+       nn := temp(Types[TINT])
+       l = append(l, Nod(OAS, nn, Nod(OADD, Nod(OLEN, s, nil), Nod(OLEN, l2, nil))))
 
+       // if uint(n) > uint(cap(s))
        nif := Nod(OIF, nil, nil)
+       nif.Left = Nod(OGT, Nod(OCONV, nn, nil), Nod(OCONV, Nod(OCAP, s, nil), nil))
+       nif.Left.Left.Type = Types[TUINT]
+       nif.Left.Right.Type = Types[TUINT]
 
-       // n := len(s) + len(l2) - cap(s)
-       nif.Ninit.Set1(Nod(OAS, nt, Nod(OSUB,
-               Nod(OADD, Nod(OLEN, s, nil), Nod(OLEN, l2, nil)),
-               Nod(OCAP, s, nil))))
-
-       nif.Left = Nod(OGT, nt, Nodintconst(0))
-
-       // instantiate growslice_n(Type*, []any, int) []any
-       fn := syslook("growslice_n") //   growslice_n(<type>, old []T, n int64) (ret []T)
+       // instantiate growslice(Type*, []any, int) []any
+       fn := syslook("growslice")
        substArgTypes(&fn, s.Type.Type, s.Type.Type)
 
-       // s = growslice_n(T, s, n)
-       nif.Nbody.Set1(Nod(OAS, s, mkcall1(fn, s.Type, &nif.Ninit, typename(s.Type), s, nt)))
-
+       // s = growslice(T, s, n)
+       nif.Nbody.Set1(Nod(OAS, s, mkcall1(fn, s.Type, &nif.Ninit, typename(s.Type), s, nn)))
        l = append(l, nif)
 
+       // s = s[:n]
+       nt := Nod(OSLICE, s, Nod(OKEY, nil, nn))
+       nt.Etype = 1
+       l = append(l, Nod(OAS, s, nt))
+
        if haspointers(l1.Type.Type) {
-               // copy(s[len(l1):len(l1)+len(l2)], l2)
-               nptr1 := Nod(OSLICE, s, Nod(OKEY, Nod(OLEN, l1, nil), Nod(OADD, Nod(OLEN, l1, nil), Nod(OLEN, l2, nil))))
+               // copy(s[len(l1):], l2)
+               nptr1 := Nod(OSLICE, s, Nod(OKEY, Nod(OLEN, l1, nil), nil))
 
                nptr1.Etype = 1
                nptr2 := l2
@@ -2838,8 +2845,8 @@ func appendslice(n *Node, init *Nodes) *Node {
                l = append(ln.Slice(), nt)
        } else if instrumenting {
                // rely on runtime to instrument copy.
-               // copy(s[len(l1):len(l1)+len(l2)], l2)
-               nptr1 := Nod(OSLICE, s, Nod(OKEY, Nod(OLEN, l1, nil), Nod(OADD, Nod(OLEN, l1, nil), Nod(OLEN, l2, nil))))
+               // copy(s[len(l1):], l2)
+               nptr1 := Nod(OSLICE, s, Nod(OKEY, Nod(OLEN, l1, nil), nil))
 
                nptr1.Etype = 1
                nptr2 := l2
@@ -2857,8 +2864,8 @@ func appendslice(n *Node, init *Nodes) *Node {
        } else {
                // memmove(&s[len(l1)], &l2[0], len(l2)*sizeof(T))
                nptr1 := Nod(OINDEX, s, Nod(OLEN, l1, nil))
-
                nptr1.Bounded = true
+
                nptr1 = Nod(OADDR, nptr1, nil)
 
                nptr2 := Nod(OSPTR, l2, nil)
@@ -2875,13 +2882,6 @@ func appendslice(n *Node, init *Nodes) *Node {
                l = append(ln.Slice(), nt)
        }
 
-       // s = s[:len(l1)+len(l2)]
-       nt = Nod(OADD, Nod(OLEN, l1, nil), Nod(OLEN, l2, nil))
-
-       nt = Nod(OSLICE, s, Nod(OKEY, nil, nt))
-       nt.Etype = 1
-       l = append(l, Nod(OAS, s, nt))
-
        typechecklist(l, Etop)
        walkstmtlist(l)
        init.Append(l...)
index bbd3e9952393af5923af9e6304dd9e881ab48fc0..c67862ebacd45f7ac77b394502a16f8d139f7380 100644 (file)
@@ -33,17 +33,6 @@ func makeslice(t *slicetype, len64, cap64 int64) slice {
        return slice{p, len, cap}
 }
 
-// growslice_n is a variant of growslice that takes the number of new elements
-// instead of the new minimum capacity.
-// TODO(rsc): This is used by append(slice, slice...).
-// The compiler should change that code to use growslice directly (issue #11419).
-func growslice_n(t *slicetype, old slice, n int) slice {
-       if n < 1 {
-               panic(errorString("growslice: invalid n"))
-       }
-       return growslice(t, old, old.cap+n)
-}
-
 // growslice handles slice growth during append.
 // It is passed the slice type, the old slice, and the desired new minimum capacity,
 // and it returns a new slice with at least that capacity, with the old data