mirror of
https://github.com/golang/go
synced 2024-11-19 12:44:51 -07: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:
parent
8ec80176d4
commit
d1341d6cf3
@ -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" +
|
||||
|
@ -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)
|
||||
|
||||
|
@ -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...)
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user