mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
cmd/compile: change Func.{Dcl,Inldcl} from NodeList to slice
A slice uses less memory than a NodeList, and has better memory locality when walking the list. This uncovered a tricky case involving closures: the escape analysis pass when run on a closure was appending to the Dcl list of the OCLOSURE rather than the ODCLFUNC. This happened to work because they shared the same NodeList. Fixed with a change to addrescapes, and a check to Tempname to catch any recurrences. This removes the last use of the listsort function outside of tests. I'll send a separate CL to remove it. Unfortunately, while this passes all tests, it does not pass toolstash -cmp. The problem is that cmpstackvarlt does not fully determine the sort order, and the change from listsort to sort.Sort, while generally desirable, produces a different ordering. I could stage this by first making cmpstackvarlt fully determined, but no matter what toolstash -cmp is going to break at some point. In my casual testing the compiler is 2.2% faster. Update #14473. Change-Id: I367d66daa4ec73ed95c14c66ccda3a2133ad95d5 Reviewed-on: https://go-review.googlesource.com/19919 Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
This commit is contained in:
parent
67dbde0d71
commit
b66a892358
21 changed files with 161 additions and 163 deletions
|
|
@ -8,6 +8,7 @@ import (
|
|||
"cmd/internal/obj"
|
||||
"crypto/md5"
|
||||
"fmt"
|
||||
"sort"
|
||||
"strings"
|
||||
)
|
||||
|
||||
|
|
@ -217,6 +218,13 @@ func cmpstackvarlt(a, b *Node) bool {
|
|||
return a.Sym.Name < b.Sym.Name
|
||||
}
|
||||
|
||||
// byStackvar implements sort.Interface for []*Node using cmpstackvarlt.
|
||||
type byStackVar []*Node
|
||||
|
||||
func (s byStackVar) Len() int { return len(s) }
|
||||
func (s byStackVar) Less(i, j int) bool { return cmpstackvarlt(s[i], s[j]) }
|
||||
func (s byStackVar) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
|
||||
|
||||
// stkdelta records the stack offset delta for a node
|
||||
// during the compaction of the stack frame to remove
|
||||
// unused stack slots.
|
||||
|
|
@ -227,25 +235,23 @@ func allocauto(ptxt *obj.Prog) {
|
|||
Stksize = 0
|
||||
stkptrsize = 0
|
||||
|
||||
if Curfn.Func.Dcl == nil {
|
||||
if len(Curfn.Func.Dcl) == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
// Mark the PAUTO's unused.
|
||||
for ll := Curfn.Func.Dcl; ll != nil; ll = ll.Next {
|
||||
if ll.N.Class == PAUTO {
|
||||
ll.N.Used = false
|
||||
for _, ln := range Curfn.Func.Dcl {
|
||||
if ln.Class == PAUTO {
|
||||
ln.Used = false
|
||||
}
|
||||
}
|
||||
|
||||
markautoused(ptxt)
|
||||
|
||||
listsort(&Curfn.Func.Dcl, cmpstackvarlt)
|
||||
sort.Sort(byStackVar(Curfn.Func.Dcl))
|
||||
|
||||
// Unused autos are at the end, chop 'em off.
|
||||
ll := Curfn.Func.Dcl
|
||||
|
||||
n := ll.N
|
||||
n := Curfn.Func.Dcl[0]
|
||||
if n.Class == PAUTO && n.Op == ONAME && !n.Used {
|
||||
// No locals used at all
|
||||
Curfn.Func.Dcl = nil
|
||||
|
|
@ -254,19 +260,17 @@ func allocauto(ptxt *obj.Prog) {
|
|||
return
|
||||
}
|
||||
|
||||
for ll := Curfn.Func.Dcl; ll.Next != nil; ll = ll.Next {
|
||||
n = ll.Next.N
|
||||
for i := 1; i < len(Curfn.Func.Dcl); i++ {
|
||||
n = Curfn.Func.Dcl[i]
|
||||
if n.Class == PAUTO && n.Op == ONAME && !n.Used {
|
||||
ll.Next = nil
|
||||
Curfn.Func.Dcl.End = ll
|
||||
Curfn.Func.Dcl = Curfn.Func.Dcl[:i]
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
// Reassign stack offsets of the locals that are still there.
|
||||
var w int64
|
||||
for ll := Curfn.Func.Dcl; ll != nil; ll = ll.Next {
|
||||
n = ll.N
|
||||
for _, n := range Curfn.Func.Dcl {
|
||||
if n.Class != PAUTO || n.Op != ONAME {
|
||||
continue
|
||||
}
|
||||
|
|
@ -298,12 +302,12 @@ func allocauto(ptxt *obj.Prog) {
|
|||
fixautoused(ptxt)
|
||||
|
||||
// The debug information needs accurate offsets on the symbols.
|
||||
for ll := Curfn.Func.Dcl; ll != nil; ll = ll.Next {
|
||||
if ll.N.Class != PAUTO || ll.N.Op != ONAME {
|
||||
for _, ln := range Curfn.Func.Dcl {
|
||||
if ln.Class != PAUTO || ln.Op != ONAME {
|
||||
continue
|
||||
}
|
||||
ll.N.Xoffset += stkdelta[ll.N]
|
||||
delete(stkdelta, ll.N)
|
||||
ln.Xoffset += stkdelta[ln]
|
||||
delete(stkdelta, ln)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -455,16 +459,15 @@ func compile(fn *Node) {
|
|||
gtrack(tracksym(t))
|
||||
}
|
||||
|
||||
for l := fn.Func.Dcl; l != nil; l = l.Next {
|
||||
n = l.N
|
||||
for _, n := range fn.Func.Dcl {
|
||||
if n.Op != ONAME { // might be OTYPE or OLITERAL
|
||||
continue
|
||||
}
|
||||
switch n.Class {
|
||||
case PAUTO, PPARAM, PPARAMOUT:
|
||||
Nodconst(&nod1, Types[TUINTPTR], l.N.Type.Width)
|
||||
p = Thearch.Gins(obj.ATYPE, l.N, &nod1)
|
||||
p.From.Gotype = Linksym(ngotype(l.N))
|
||||
Nodconst(&nod1, Types[TUINTPTR], n.Type.Width)
|
||||
p = Thearch.Gins(obj.ATYPE, n, &nod1)
|
||||
p.From.Gotype = Linksym(ngotype(n))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue