1
0
mirror of https://github.com/golang/go synced 2024-10-02 04:28:33 -06:00

cmd/compile, runtime: eliminate growslice_n

Fixes #11419.

Change-Id: I7935a253e3e96191a33f5041bab203ecc5f0c976
Reviewed-on: https://go-review.googlesource.com/20647
Reviewed-by: Keith Randall <khr@golang.org>
This commit is contained in:
Matthew Dempsky 2016-03-13 15:22:45 -07:00
parent 8ec80176d4
commit d1341d6cf3
4 changed files with 29 additions and 42 deletions

View File

@ -128,7 +128,6 @@ const runtimeimport = "" +
"func @\"\".block ()\n" + "func @\"\".block ()\n" +
"func @\"\".makeslice (@\"\".typ·2 *byte, @\"\".nel·3 int64, @\"\".cap·4 int64) (@\"\".ary·1 []any)\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 (@\"\".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 @\"\".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 @\"\".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" + "func @\"\".memequal (@\"\".x·2 *any, @\"\".y·3 *any, @\"\".size·4 uintptr \"unsafe-uintptr\") (? bool)\n" +

View File

@ -165,7 +165,6 @@ func block()
func makeslice(typ *byte, nel int64, cap int64) (ary []any) func makeslice(typ *byte, nel int64, cap int64) (ary []any)
func growslice(typ *byte, old []any, cap int) (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 memmove(to *any, frm *any, length uintptr)
func memclr(ptr *byte, length uintptr) func memclr(ptr *byte, length uintptr)

View File

@ -2777,10 +2777,12 @@ func addstr(n *Node, init *Nodes) *Node {
// expand append(l1, l2...) to // expand append(l1, l2...) to
// init { // init {
// s := l1 // s := l1
// if n := len(l1) + len(l2) - cap(s); n > 0 { // n := len(s) + len(l2)
// s = growslice_n(s, n) // // 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)) // memmove(&s[len(l1)], &l2[0], len(l2)*sizeof(T))
// } // }
// s // s
@ -2800,33 +2802,38 @@ func appendslice(n *Node, init *Nodes) *Node {
l1 := n.List.First() l1 := n.List.First()
l2 := n.List.Second() l2 := n.List.Second()
s := temp(l1.Type) // var s []T
var l []*Node var l []*Node
// var s []T
s := temp(l1.Type)
l = append(l, Nod(OAS, s, l1)) // s = l1 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 := 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) // instantiate growslice(Type*, []any, int) []any
nif.Ninit.Set1(Nod(OAS, nt, Nod(OSUB, fn := syslook("growslice")
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)
substArgTypes(&fn, s.Type.Type, s.Type.Type) substArgTypes(&fn, s.Type.Type, s.Type.Type)
// s = growslice_n(T, s, n) // s = growslice(T, s, n)
nif.Nbody.Set1(Nod(OAS, s, mkcall1(fn, s.Type, &nif.Ninit, typename(s.Type), s, nt))) nif.Nbody.Set1(Nod(OAS, s, mkcall1(fn, s.Type, &nif.Ninit, typename(s.Type), s, nn)))
l = append(l, nif) 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) { if haspointers(l1.Type.Type) {
// copy(s[len(l1):len(l1)+len(l2)], l2) // copy(s[len(l1):], l2)
nptr1 := Nod(OSLICE, s, Nod(OKEY, Nod(OLEN, l1, nil), Nod(OADD, Nod(OLEN, l1, nil), Nod(OLEN, l2, nil)))) nptr1 := Nod(OSLICE, s, Nod(OKEY, Nod(OLEN, l1, nil), nil))
nptr1.Etype = 1 nptr1.Etype = 1
nptr2 := l2 nptr2 := l2
@ -2838,8 +2845,8 @@ func appendslice(n *Node, init *Nodes) *Node {
l = append(ln.Slice(), nt) l = append(ln.Slice(), nt)
} else if instrumenting { } else if instrumenting {
// rely on runtime to instrument copy. // rely on runtime to instrument copy.
// copy(s[len(l1):len(l1)+len(l2)], l2) // copy(s[len(l1):], l2)
nptr1 := Nod(OSLICE, s, Nod(OKEY, Nod(OLEN, l1, nil), Nod(OADD, Nod(OLEN, l1, nil), Nod(OLEN, l2, nil)))) nptr1 := Nod(OSLICE, s, Nod(OKEY, Nod(OLEN, l1, nil), nil))
nptr1.Etype = 1 nptr1.Etype = 1
nptr2 := l2 nptr2 := l2
@ -2857,8 +2864,8 @@ func appendslice(n *Node, init *Nodes) *Node {
} else { } else {
// memmove(&s[len(l1)], &l2[0], len(l2)*sizeof(T)) // memmove(&s[len(l1)], &l2[0], len(l2)*sizeof(T))
nptr1 := Nod(OINDEX, s, Nod(OLEN, l1, nil)) nptr1 := Nod(OINDEX, s, Nod(OLEN, l1, nil))
nptr1.Bounded = true nptr1.Bounded = true
nptr1 = Nod(OADDR, nptr1, nil) nptr1 = Nod(OADDR, nptr1, nil)
nptr2 := Nod(OSPTR, l2, nil) nptr2 := Nod(OSPTR, l2, nil)
@ -2875,13 +2882,6 @@ func appendslice(n *Node, init *Nodes) *Node {
l = append(ln.Slice(), nt) 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) typechecklist(l, Etop)
walkstmtlist(l) walkstmtlist(l)
init.Append(l...) init.Append(l...)

View File

@ -33,17 +33,6 @@ func makeslice(t *slicetype, len64, cap64 int64) slice {
return slice{p, len, cap} 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. // growslice handles slice growth during append.
// It is passed the slice type, the old slice, and the desired new minimum capacity, // 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 // and it returns a new slice with at least that capacity, with the old data