]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/compile: change Func.{Dcl,Inldcl} from NodeList to slice
authorIan Lance Taylor <iant@golang.org>
Thu, 25 Feb 2016 18:35:19 +0000 (10:35 -0800)
committerIan Lance Taylor <iant@golang.org>
Fri, 26 Feb 2016 20:43:23 +0000 (20:43 +0000)
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>
21 files changed:
src/cmd/compile/internal/amd64/ggen.go
src/cmd/compile/internal/arm/ggen.go
src/cmd/compile/internal/arm64/ggen.go
src/cmd/compile/internal/gc/cgen.go
src/cmd/compile/internal/gc/closure.go
src/cmd/compile/internal/gc/dcl.go
src/cmd/compile/internal/gc/esc.go
src/cmd/compile/internal/gc/gen.go
src/cmd/compile/internal/gc/gsubr.go
src/cmd/compile/internal/gc/inl.go
src/cmd/compile/internal/gc/parser.go
src/cmd/compile/internal/gc/pgen.go
src/cmd/compile/internal/gc/plive.go
src/cmd/compile/internal/gc/popt.go
src/cmd/compile/internal/gc/subr.go
src/cmd/compile/internal/gc/syntax.go
src/cmd/compile/internal/gc/typecheck.go
src/cmd/compile/internal/gc/walk.go
src/cmd/compile/internal/mips64/ggen.go
src/cmd/compile/internal/ppc64/ggen.go
src/cmd/compile/internal/x86/ggen.go

index b9e5bfb15fc3dab843968965e608546def2a681f..55fb9e0a43311a4379b0c4c82549656a4f11a917 100644 (file)
@@ -14,8 +14,6 @@ import (
 var isPlan9 = obj.Getgoos() == "plan9"
 
 func defframe(ptxt *obj.Prog) {
-       var n *gc.Node
-
        // fill in argument size, stack size
        ptxt.To.Type = obj.TYPE_TEXTSIZE
 
@@ -34,8 +32,7 @@ func defframe(ptxt *obj.Prog) {
        x0 := uint32(0)
 
        // iterate through declarations - they are sorted in decreasing xoffset order.
-       for l := gc.Curfn.Func.Dcl; l != nil; l = l.Next {
-               n = l.N
+       for _, n := range gc.Curfn.Func.Dcl {
                if !n.Name.Needzero {
                        continue
                }
index 517b4f4c8e9e33659b0cca4385913b51fa7d9b6b..5e282c8cd59bbd88f5b50984a4f5376454530b8e 100644 (file)
@@ -11,8 +11,6 @@ import (
 )
 
 func defframe(ptxt *obj.Prog) {
-       var n *gc.Node
-
        // fill in argument size, stack size
        ptxt.To.Type = obj.TYPE_TEXTSIZE
 
@@ -28,8 +26,7 @@ func defframe(ptxt *obj.Prog) {
        hi := int64(0)
        lo := hi
        r0 := uint32(0)
-       for l := gc.Curfn.Func.Dcl; l != nil; l = l.Next {
-               n = l.N
+       for _, n := range gc.Curfn.Func.Dcl {
                if !n.Name.Needzero {
                        continue
                }
index 99ffd5acd56d6a466aa30316b0dcc59e7991b0c1..a33b2b42bfffa8c15f6b6e69a37746a845ce0c33 100644 (file)
@@ -12,8 +12,6 @@ import (
 )
 
 func defframe(ptxt *obj.Prog) {
-       var n *gc.Node
-
        // fill in argument size, stack size
        ptxt.To.Type = obj.TYPE_TEXTSIZE
 
@@ -37,8 +35,7 @@ func defframe(ptxt *obj.Prog) {
        lo := hi
 
        // iterate through declarations - they are sorted in decreasing xoffset order.
-       for l := gc.Curfn.Func.Dcl; l != nil; l = l.Next {
-               n = l.N
+       for _, n := range gc.Curfn.Func.Dcl {
                if !n.Name.Needzero {
                        continue
                }
index 6456240a12da1556f12a33c42a65856c7269b127..fdeb6e65f7912c83d2799f32958af91aade0748d 100644 (file)
@@ -2263,9 +2263,9 @@ func sgen_wb(n *Node, ns *Node, w int64, wb bool) {
        // If copying .args, that's all the results, so record definition sites
        // for them for the liveness analysis.
        if ns.Op == ONAME && ns.Sym.Name == ".args" {
-               for l := Curfn.Func.Dcl; l != nil; l = l.Next {
-                       if l.N.Class == PPARAMOUT {
-                               Gvardef(l.N)
+               for _, ln := range Curfn.Func.Dcl {
+                       if ln.Class == PPARAMOUT {
+                               Gvardef(ln)
                        }
                }
        }
index df3e31a7ec687ae71160aef7c4bb9651094ae2d1..df36db118d55d10516cb88a71f1cb4cda5aea5f5 100644 (file)
@@ -96,9 +96,9 @@ func typecheckclosure(func_ *Node, top int) {
                }
        }
 
-       for l := func_.Func.Dcl; l != nil; l = l.Next {
-               if l.N.Op == ONAME && (l.N.Class == PPARAM || l.N.Class == PPARAMOUT) {
-                       l.N.Name.Decldepth = 1
+       for _, ln := range func_.Func.Dcl {
+               if ln.Op == ONAME && (ln.Class == PPARAM || ln.Class == PPARAMOUT) {
+                       ln.Name.Decldepth = 1
                }
        }
 
@@ -198,7 +198,8 @@ func makeclosure(func_ *Node) *Node {
        makefuncsym(xfunc.Func.Nname.Sym)
 
        xfunc.Nbody = func_.Nbody
-       xfunc.Func.Dcl = concat(func_.Func.Dcl, xfunc.Func.Dcl)
+       xfunc.Func.Dcl = append(func_.Func.Dcl, xfunc.Func.Dcl...)
+       func_.Func.Dcl = nil
        if xfunc.Nbody == nil {
                Fatalf("empty body - won't generate any code")
        }
@@ -341,13 +342,13 @@ func transformclosure(xfunc *Node) {
                        fld.Sym = fld.Nname.Sym
 
                        // Declare the new param and add it the first part of the input arguments.
-                       xfunc.Func.Dcl = list(xfunc.Func.Dcl, fld.Nname)
+                       xfunc.Func.Dcl = append(xfunc.Func.Dcl, fld.Nname)
 
                        *param = fld
                        param = &fld.Down
                }
                *param = original_args
-               xfunc.Func.Dcl = concat(xfunc.Func.Dcl, original_dcl)
+               xfunc.Func.Dcl = append(xfunc.Func.Dcl, original_dcl...)
 
                // Recalculate param offsets.
                if f.Type.Width > 0 {
@@ -386,7 +387,7 @@ func transformclosure(xfunc *Node) {
                                // If it is a small variable captured by value, downgrade it to PAUTO.
                                v.Class = PAUTO
                                v.Ullman = 1
-                               xfunc.Func.Dcl = list(xfunc.Func.Dcl, v)
+                               xfunc.Func.Dcl = append(xfunc.Func.Dcl, v)
                                body = list(body, Nod(OAS, v, cv))
                        } else {
                                // Declare variable holding addresses taken from closure
@@ -396,7 +397,7 @@ func transformclosure(xfunc *Node) {
                                addr.Class = PAUTO
                                addr.Used = true
                                addr.Name.Curfn = xfunc
-                               xfunc.Func.Dcl = list(xfunc.Func.Dcl, addr)
+                               xfunc.Func.Dcl = append(xfunc.Func.Dcl, addr)
                                v.Name.Heapaddr = addr
                                if v.Name.Byval {
                                        cv = Nod(OADDR, cv, nil)
@@ -551,7 +552,7 @@ func makepartialcall(fn *Node, t0 *Type, meth *Node) *Node {
                n = newname(Lookupf("a%d", i))
                i++
                n.Class = PPARAM
-               xfunc.Func.Dcl = list(xfunc.Func.Dcl, n)
+               xfunc.Func.Dcl = append(xfunc.Func.Dcl, n)
                callargs = list(callargs, n)
                fld = Nod(ODCLFIELD, n, typenod(t.Type))
                if t.Isddd {
@@ -570,7 +571,7 @@ func makepartialcall(fn *Node, t0 *Type, meth *Node) *Node {
                n = newname(Lookupf("r%d", i))
                i++
                n.Class = PPARAMOUT
-               xfunc.Func.Dcl = list(xfunc.Func.Dcl, n)
+               xfunc.Func.Dcl = append(xfunc.Func.Dcl, n)
                retargs = list(retargs, n)
                l = list(l, Nod(ODCLFIELD, n, typenod(t.Type)))
        }
@@ -600,7 +601,7 @@ func makepartialcall(fn *Node, t0 *Type, meth *Node) *Node {
        ptr.Ullman = 1
        ptr.Used = true
        ptr.Name.Curfn = xfunc
-       xfunc.Func.Dcl = list(xfunc.Func.Dcl, ptr)
+       xfunc.Func.Dcl = append(xfunc.Func.Dcl, ptr)
        var body *NodeList
        if Isptr[rcvrtype.Etype] || Isinter(rcvrtype) {
                ptr.Name.Param.Ntype = typenod(rcvrtype)
index 7e44a4756da50fa7e60f196fc4015a0c4f53eaaa..ccbb2d9d70bf84be8b1fda91fc6e27a48e50226d 100644 (file)
@@ -187,7 +187,7 @@ func declare(n *Node, ctxt Class) {
                        Fatalf("automatic outside function")
                }
                if Curfn != nil {
-                       Curfn.Func.Dcl = list(Curfn.Func.Dcl, n)
+                       Curfn.Func.Dcl = append(Curfn.Func.Dcl, n)
                }
                if n.Op == OTYPE {
                        declare_typegen++
index 1a5a433eebdd923f46f25b9b0d9f0b543e7abbbf..4cafc839cfd81d8cf405297c8fddf679db8ab1ea 100644 (file)
@@ -476,35 +476,35 @@ func escfunc(e *EscState, func_ *Node) {
        savefn := Curfn
        Curfn = func_
 
-       for ll := Curfn.Func.Dcl; ll != nil; ll = ll.Next {
-               if ll.N.Op != ONAME {
+       for _, ln := range Curfn.Func.Dcl {
+               if ln.Op != ONAME {
                        continue
                }
-               llNE := e.nodeEscState(ll.N)
-               switch ll.N.Class {
+               llNE := e.nodeEscState(ln)
+               switch ln.Class {
                // out params are in a loopdepth between the sink and all local variables
                case PPARAMOUT:
                        llNE.Escloopdepth = 0
 
                case PPARAM:
                        llNE.Escloopdepth = 1
-                       if ll.N.Type != nil && !haspointers(ll.N.Type) {
+                       if ln.Type != nil && !haspointers(ln.Type) {
                                break
                        }
                        if Curfn.Nbody == nil && !Curfn.Noescape {
-                               ll.N.Esc = EscHeap
+                               ln.Esc = EscHeap
                        } else {
-                               ll.N.Esc = EscNone // prime for escflood later
+                               ln.Esc = EscNone // prime for escflood later
                        }
-                       e.noesc = list(e.noesc, ll.N)
+                       e.noesc = list(e.noesc, ln)
                }
        }
 
        // in a mutually recursive group we lose track of the return values
        if e.recursive {
-               for ll := Curfn.Func.Dcl; ll != nil; ll = ll.Next {
-                       if ll.N.Op == ONAME && ll.N.Class == PPARAMOUT {
-                               escflows(e, &e.theSink, ll.N)
+               for _, ln := range Curfn.Func.Dcl {
+                       if ln.Op == ONAME && ln.Class == PPARAMOUT {
+                               escflows(e, &e.theSink, ln)
                        }
                }
        }
@@ -779,11 +779,14 @@ func esc(e *EscState, n *Node, up *Node) {
                        ll = e.nodeEscState(n.List.N).Escretval
                }
 
-               for lr := Curfn.Func.Dcl; lr != nil && ll != nil; lr = lr.Next {
-                       if lr.N.Op != ONAME || lr.N.Class != PPARAMOUT {
+               for _, lrn := range Curfn.Func.Dcl {
+                       if ll == nil {
+                               break
+                       }
+                       if lrn.Op != ONAME || lrn.Class != PPARAMOUT {
                                continue
                        }
-                       escassign(e, lr.N, ll.N)
+                       escassign(e, lrn, ll.N)
                        ll = ll.Next
                }
 
@@ -1870,16 +1873,16 @@ func esctag(e *EscState, func_ *Node) {
        savefn := Curfn
        Curfn = func_
 
-       for ll := Curfn.Func.Dcl; ll != nil; ll = ll.Next {
-               if ll.N.Op != ONAME {
+       for _, ln := range Curfn.Func.Dcl {
+               if ln.Op != ONAME {
                        continue
                }
 
-               switch ll.N.Esc & EscMask {
+               switch ln.Esc & EscMask {
                case EscNone, // not touched by escflood
                        EscReturn:
-                       if haspointers(ll.N.Type) { // don't bother tagging for scalars
-                               ll.N.Name.Param.Field.Note = mktag(int(ll.N.Esc))
+                       if haspointers(ln.Type) { // don't bother tagging for scalars
+                               ln.Name.Param.Field.Note = mktag(int(ln.Esc))
                        }
 
                case EscHeap, // touched by escflood, moved to heap
index b7560556683a2de0cb2d0e816f7ad9d2e2368241..adebfb81d0f65ed5056bad407233eadd60ed74ee 100644 (file)
@@ -76,6 +76,9 @@ func addrescapes(n *Node) {
                        oldfn := Curfn
 
                        Curfn = n.Name.Curfn
+                       if Curfn.Func.Closure != nil && Curfn.Op == OCLOSURE {
+                               Curfn = Curfn.Func.Closure
+                       }
                        n.Name.Heapaddr = temp(Ptrto(n.Type))
                        buf := fmt.Sprintf("&%v", n.Sym)
                        n.Name.Heapaddr.Sym = Lookup(buf)
@@ -585,6 +588,10 @@ func Tempname(nn *Node, t *Type) {
        if Curfn == nil {
                Fatalf("no curfn for tempname")
        }
+       if Curfn.Func.Closure != nil && Curfn.Op == OCLOSURE {
+               Dump("Tempname", Curfn)
+               Fatalf("adding tempname to wrong closure function")
+       }
 
        if t == nil {
                Yyerror("tempname called with nil type")
@@ -604,7 +611,7 @@ func Tempname(nn *Node, t *Type) {
        n.Ullman = 1
        n.Esc = EscNever
        n.Name.Curfn = Curfn
-       Curfn.Func.Dcl = list(Curfn.Func.Dcl, n)
+       Curfn.Func.Dcl = append(Curfn.Func.Dcl, n)
 
        dowidth(t)
        n.Xoffset = 0
index 04e986562dd3f29223eae161179ced3bbd34886f..f5d7a8d2de26aa7f534d841892756f644db478f7 100644 (file)
@@ -556,9 +556,7 @@ func nodarg(t *Type, fp int) *Node {
        }
 
        if fp == 1 {
-               var n *Node
-               for l := Curfn.Func.Dcl; l != nil; l = l.Next {
-                       n = l.N
+               for _, n := range Curfn.Func.Dcl {
                        if (n.Class == PPARAM || n.Class == PPARAMOUT) && !isblanksym(t.Sym) && n.Sym == t.Sym {
                                return n
                        }
index a445f712e278af3868f90f740231a2f34f298759..cae15f91dee460f3d1782a1fcd2a8a36c4d6ff5a 100644 (file)
@@ -150,7 +150,7 @@ func caninl(fn *Node) {
 
        fn.Func.Nname.Func.Inl = fn.Nbody
        fn.Nbody = inlcopylist(fn.Func.Nname.Func.Inl)
-       fn.Func.Nname.Func.Inldcl = inlcopylist(fn.Func.Nname.Name.Defn.Func.Dcl)
+       fn.Func.Nname.Func.Inldcl = inlcopyslice(fn.Func.Nname.Name.Defn.Func.Dcl)
        fn.Func.Nname.Func.InlCost = int32(maxBudget - budget)
 
        // hack, TODO, check for better way to link method nodes back to the thing with the ->inl
@@ -275,6 +275,18 @@ func inlcopy(n *Node) *Node {
        return m
 }
 
+// Inlcopyslice is like inlcopylist, but for a slice.
+func inlcopyslice(ll []*Node) []*Node {
+       r := make([]*Node, 0, len(ll))
+       for _, ln := range ll {
+               c := inlcopy(ln)
+               if c != nil {
+                       r = append(r, c)
+               }
+       }
+       return r
+}
+
 // Inlcalls/nodelist/node walks fn's statements and expressions and substitutes any
 // calls made to inlineable functions.  This is the external entry point.
 func inlcalls(fn *Node) {
@@ -556,7 +568,7 @@ func mkinlcall1(np **Node, fn *Node, isddd bool) {
 
        //dumplist("ninit pre", ninit);
 
-       var dcl *NodeList
+       var dcl []*Node
        if fn.Name.Defn != nil { // local function
                dcl = fn.Func.Inldcl // imported function
        } else {
@@ -567,18 +579,18 @@ func mkinlcall1(np **Node, fn *Node, isddd bool) {
        i := 0
 
        // Make temp names to use instead of the originals
-       for ll := dcl; ll != nil; ll = ll.Next {
-               if ll.N.Class == PPARAMOUT { // return values handled below.
+       for _, ln := range dcl {
+               if ln.Class == PPARAMOUT { // return values handled below.
                        continue
                }
-               if ll.N.Op == ONAME {
-                       ll.N.Name.Inlvar = inlvar(ll.N)
+               if ln.Op == ONAME {
+                       ln.Name.Inlvar = inlvar(ln)
 
                        // Typecheck because inlvar is not necessarily a function parameter.
-                       typecheck(&ll.N.Name.Inlvar, Erv)
+                       typecheck(&ln.Name.Inlvar, Erv)
 
-                       if ll.N.Class&^PHEAP != PAUTO {
-                               ninit = list(ninit, Nod(ODCL, ll.N.Name.Inlvar, nil)) // otherwise gen won't emit the allocations for heapallocs
+                       if ln.Class&^PHEAP != PAUTO {
+                               ninit = list(ninit, Nod(ODCL, ln.Name.Inlvar, nil)) // otherwise gen won't emit the allocations for heapallocs
                        }
                }
        }
@@ -852,7 +864,7 @@ func inlvar(var_ *Node) *Node {
                addrescapes(n)
        }
 
-       Curfn.Func.Dcl = list(Curfn.Func.Dcl, n)
+       Curfn.Func.Dcl = append(Curfn.Func.Dcl, n)
        return n
 }
 
@@ -863,7 +875,7 @@ func retvar(t *Type, i int) *Node {
        n.Class = PAUTO
        n.Used = true
        n.Name.Curfn = Curfn // the calling function, not the called one
-       Curfn.Func.Dcl = list(Curfn.Func.Dcl, n)
+       Curfn.Func.Dcl = append(Curfn.Func.Dcl, n)
        return n
 }
 
@@ -875,7 +887,7 @@ func argvar(t *Type, i int) *Node {
        n.Class = PAUTO
        n.Used = true
        n.Name.Curfn = Curfn // the calling function, not the called one
-       Curfn.Func.Dcl = list(Curfn.Func.Dcl, n)
+       Curfn.Func.Dcl = append(Curfn.Func.Dcl, n)
        return n
 }
 
index ffa20711b774e6085d3ed0b7650a8050c7934187..88d45118da132b9937f8bc56573e81534cfca476 100644 (file)
@@ -2564,15 +2564,15 @@ func (p *parser) stmt() *Node {
                stmt := Nod(ORETURN, nil, nil)
                stmt.List = results
                if stmt.List == nil && Curfn != nil {
-                       for l := Curfn.Func.Dcl; l != nil; l = l.Next {
-                               if l.N.Class == PPARAM {
+                       for _, ln := range Curfn.Func.Dcl {
+                               if ln.Class == PPARAM {
                                        continue
                                }
-                               if l.N.Class != PPARAMOUT {
+                               if ln.Class != PPARAMOUT {
                                        break
                                }
-                               if l.N.Sym.Def != l.N {
-                                       Yyerror("%s is shadowed during return", l.N.Sym.Name)
+                               if ln.Sym.Def != ln {
+                                       Yyerror("%s is shadowed during return", ln.Sym.Name)
                                }
                        }
                }
index 3471b977ed113bd4d6442bfc7b4d53157fa01f3e..a44cc734f658bc965188d744764a3b0eaa70a476 100644 (file)
@@ -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))
                }
        }
 
index 8719029c914019d3083b76dd12514e62d3a8555f..84a24a827a7fcc1f715e15d95c843fc89604aa63 100644 (file)
@@ -197,8 +197,8 @@ func blockany(bb *BasicBlock, f func(*obj.Prog) bool) bool {
 // variables.
 func getvariables(fn *Node) []*Node {
        result := make([]*Node, 0, 0)
-       for ll := fn.Func.Dcl; ll != nil; ll = ll.Next {
-               if ll.N.Op == ONAME {
+       for _, ln := range fn.Func.Dcl {
+               if ln.Op == ONAME {
                        // In order for GODEBUG=gcdead=1 to work, each bitmap needs
                        // to contain information about all variables covered by the bitmap.
                        // For local variables, the bitmap only covers the stkptrsize
@@ -218,24 +218,24 @@ func getvariables(fn *Node) []*Node {
                        // Later, when we want to find the index of a node in the variables list,
                        // we will check that n->curfn == curfn and n->opt > 0. Then n->opt - 1
                        // is the index in the variables list.
-                       ll.N.SetOpt(nil)
+                       ln.SetOpt(nil)
 
                        // The compiler doesn't emit initializations for zero-width parameters or results.
-                       if ll.N.Type.Width == 0 {
+                       if ln.Type.Width == 0 {
                                continue
                        }
 
-                       ll.N.Name.Curfn = Curfn
-                       switch ll.N.Class {
+                       ln.Name.Curfn = Curfn
+                       switch ln.Class {
                        case PAUTO:
-                               if haspointers(ll.N.Type) {
-                                       ll.N.SetOpt(int32(len(result)))
-                                       result = append(result, ll.N)
+                               if haspointers(ln.Type) {
+                                       ln.SetOpt(int32(len(result)))
+                                       result = append(result, ln)
                                }
 
                        case PPARAM, PPARAMOUT:
-                               ll.N.SetOpt(int32(len(result)))
-                               result = append(result, ll.N)
+                               ln.SetOpt(int32(len(result)))
+                               result = append(result, ln)
                        }
                }
        }
@@ -795,8 +795,8 @@ func livenessprintcfg(lv *Liveness) {
 }
 
 func checkauto(fn *Node, p *obj.Prog, n *Node) {
-       for l := fn.Func.Dcl; l != nil; l = l.Next {
-               if l.N.Op == ONAME && l.N.Class == PAUTO && l.N == n {
+       for _, ln := range fn.Func.Dcl {
+               if ln.Op == ONAME && ln.Class == PAUTO && ln == n {
                        return
                }
        }
@@ -807,8 +807,8 @@ func checkauto(fn *Node, p *obj.Prog, n *Node) {
        }
 
        fmt.Printf("checkauto %v: %v (%p; class=%d) not found in %p %v\n", funcSym(Curfn), n, n, n.Class, p, p)
-       for l := fn.Func.Dcl; l != nil; l = l.Next {
-               fmt.Printf("\t%v (%p; class=%d)\n", l.N, l.N, l.N.Class)
+       for _, ln := range fn.Func.Dcl {
+               fmt.Printf("\t%v (%p; class=%d)\n", ln, ln, ln.Class)
        }
        Yyerror("checkauto: invariant lost")
 }
@@ -817,10 +817,8 @@ func checkparam(fn *Node, p *obj.Prog, n *Node) {
        if isfunny(n) {
                return
        }
-       var a *Node
        var class Class
-       for l := fn.Func.Dcl; l != nil; l = l.Next {
-               a = l.N
+       for _, a := range fn.Func.Dcl {
                class = a.Class &^ PHEAP
                if a.Op == ONAME && (class == PPARAM || class == PPARAMOUT) && a == n {
                        return
@@ -828,8 +826,8 @@ func checkparam(fn *Node, p *obj.Prog, n *Node) {
        }
 
        fmt.Printf("checkparam %v: %v (%p; class=%d) not found in %v\n", Curfn, n, n, n.Class, p)
-       for l := fn.Func.Dcl; l != nil; l = l.Next {
-               fmt.Printf("\t%v (%p; class=%d)\n", l.N, l.N, l.N.Class)
+       for _, ln := range fn.Func.Dcl {
+               fmt.Printf("\t%v (%p; class=%d)\n", ln, ln, ln.Class)
        }
        Yyerror("checkparam: invariant lost")
 }
@@ -1807,9 +1805,9 @@ func liveness(fn *Node, firstp *obj.Prog, argssym *Sym, livesym *Sym) {
        onebitwritesymbol(lv.argslivepointers, argssym)
 
        // Free everything.
-       for l := fn.Func.Dcl; l != nil; l = l.Next {
-               if l.N != nil {
-                       l.N.SetOpt(nil)
+       for _, ln := range fn.Func.Dcl {
+               if ln != nil {
+                       ln.SetOpt(nil)
                }
        }
        freeliveness(lv)
index 6eb5c7b60cd162c32f0e106d11fedaa5539cd6e7..0a2d8c45d41673ba24c79e0b843eeeaa99fed0d2 100644 (file)
@@ -589,8 +589,8 @@ func mergetemp(firstp *obj.Prog) {
 
        // Build list of all mergeable variables.
        var vars []*TempVar
-       for l := Curfn.Func.Dcl; l != nil; l = l.Next {
-               if n := l.N; canmerge(n) {
+       for _, n := range Curfn.Func.Dcl {
+               if canmerge(n) {
                        v := &TempVar{}
                        vars = append(vars, v)
                        n.SetOpt(v)
@@ -819,22 +819,15 @@ func mergetemp(firstp *obj.Prog) {
        }
 
        // Delete merged nodes from declaration list.
-       for lp := &Curfn.Func.Dcl; ; {
-               l := *lp
-               if l == nil {
-                       break
-               }
-
-               Curfn.Func.Dcl.End = l
-               n := l.N
+       dcl := make([]*Node, 0, len(Curfn.Func.Dcl)-nkill)
+       for _, n := range Curfn.Func.Dcl {
                v, _ := n.Opt().(*TempVar)
                if v != nil && (v.merge != nil || v.removed) {
-                       *lp = l.Next
                        continue
                }
-
-               lp = &l.Next
+               dcl = append(dcl, n)
        }
+       Curfn.Func.Dcl = dcl
 
        // Clear aux structures.
        for _, v := range vars {
index 5287626aae5092a112a5db7718ea1cf8652b6c61..a48097122afb5bd9775b8f38a623d17a5ac0f455 100644 (file)
@@ -1543,8 +1543,8 @@ func frame(context int) {
 
        if Curfn != nil {
                fmt.Printf("--- %v frame ---\n", Curfn.Func.Nname.Sym)
-               for l := Curfn.Func.Dcl; l != nil; l = l.Next {
-                       printframenode(l.N)
+               for _, ln := range Curfn.Func.Dcl {
+                       printframenode(ln)
                }
        }
 }
index a11b37e2ad083153099493c7b0b163cde5951f50..adf447de01cd351fbe64b07ed75050355091e342 100644 (file)
@@ -152,8 +152,8 @@ type Func struct {
        Enter      *NodeList
        Exit       *NodeList
        Cvars      *NodeList // closure params
-       Dcl        *NodeList // autodcl for this func/closure
-       Inldcl     *NodeList // copy of dcl for use in inlining
+       Dcl        []*Node   // autodcl for this func/closure
+       Inldcl     []*Node   // copy of dcl for use in inlining
        Closgen    int
        Outerfunc  *Node
        Fieldtrack []*Type
index 8fd6f8557500a55d684364e1f27adf0b242668e6..395f04c21b5492c96687ff4d6c69da6620592ac8 100644 (file)
@@ -3433,9 +3433,9 @@ func typecheckfunc(n *Node) {
                addmethod(n.Func.Shortname.Sym, t, true, n.Func.Nname.Nointerface)
        }
 
-       for l := n.Func.Dcl; l != nil; l = l.Next {
-               if l.N.Op == ONAME && (l.N.Class == PPARAM || l.N.Class == PPARAMOUT) {
-                       l.N.Name.Decldepth = 1
+       for _, ln := range n.Func.Dcl {
+               if ln.Op == ONAME && (ln.Class == PPARAM || ln.Class == PPARAMOUT) {
+                       ln.Name.Decldepth = 1
                }
        }
 }
index f324d5e00f1cda05a763854e5d7fe2215883bf1b..acc923a866883438bcd213c88581b3e749666e76 100644 (file)
@@ -29,33 +29,34 @@ func walk(fn *Node) {
 
        // Final typecheck for any unused variables.
        // It's hard to be on the heap when not-used, but best to be consistent about &~PHEAP here and below.
-       for l := fn.Func.Dcl; l != nil; l = l.Next {
-               if l.N.Op == ONAME && l.N.Class&^PHEAP == PAUTO {
-                       typecheck(&l.N, Erv|Easgn)
+       for i, ln := range fn.Func.Dcl {
+               if ln.Op == ONAME && ln.Class&^PHEAP == PAUTO {
+                       typecheck(&ln, Erv|Easgn)
+                       fn.Func.Dcl[i] = ln
                }
        }
 
        // Propagate the used flag for typeswitch variables up to the NONAME in it's definition.
-       for l := fn.Func.Dcl; l != nil; l = l.Next {
-               if l.N.Op == ONAME && l.N.Class&^PHEAP == PAUTO && l.N.Name.Defn != nil && l.N.Name.Defn.Op == OTYPESW && l.N.Used {
-                       l.N.Name.Defn.Left.Used = true
+       for _, ln := range fn.Func.Dcl {
+               if ln.Op == ONAME && ln.Class&^PHEAP == PAUTO && ln.Name.Defn != nil && ln.Name.Defn.Op == OTYPESW && ln.Used {
+                       ln.Name.Defn.Left.Used = true
                }
        }
 
-       for l := fn.Func.Dcl; l != nil; l = l.Next {
-               if l.N.Op != ONAME || l.N.Class&^PHEAP != PAUTO || l.N.Sym.Name[0] == '&' || l.N.Used {
+       for _, ln := range fn.Func.Dcl {
+               if ln.Op != ONAME || ln.Class&^PHEAP != PAUTO || ln.Sym.Name[0] == '&' || ln.Used {
                        continue
                }
-               if defn := l.N.Name.Defn; defn != nil && defn.Op == OTYPESW {
+               if defn := ln.Name.Defn; defn != nil && defn.Op == OTYPESW {
                        if defn.Left.Used {
                                continue
                        }
                        lineno = defn.Left.Lineno
-                       Yyerror("%v declared and not used", l.N.Sym)
+                       Yyerror("%v declared and not used", ln.Sym)
                        defn.Left.Used = true // suppress repeats
                } else {
-                       lineno = l.N.Lineno
-                       Yyerror("%v declared and not used", l.N.Sym)
+                       lineno = ln.Lineno
+                       Yyerror("%v declared and not used", ln.Sym)
                }
        }
 
@@ -92,11 +93,11 @@ func samelist(a *NodeList, b *NodeList) bool {
 }
 
 func paramoutheap(fn *Node) bool {
-       for l := fn.Func.Dcl; l != nil; l = l.Next {
-               switch l.N.Class {
+       for _, ln := range fn.Func.Dcl {
+               switch ln.Class {
                case PPARAMOUT,
                        PPARAMOUT | PHEAP:
-                       return l.N.Addrtaken
+                       return ln.Addrtaken
 
                        // stop early - parameters are over
                case PAUTO,
@@ -290,13 +291,13 @@ func walkstmt(np **Node) {
                        var rl *NodeList
 
                        var cl Class
-                       for ll := Curfn.Func.Dcl; ll != nil; ll = ll.Next {
-                               cl = ll.N.Class &^ PHEAP
+                       for _, ln := range Curfn.Func.Dcl {
+                               cl = ln.Class &^ PHEAP
                                if cl == PAUTO {
                                        break
                                }
                                if cl == PPARAMOUT {
-                                       rl = list(rl, ll.N)
+                                       rl = list(rl, ln)
                                }
                        }
 
index 8c285a29525b5ed67596e96e0caaac7d0dd1c8f3..429eb351a261139af919851f70a92eab33aa2653 100644 (file)
@@ -12,8 +12,6 @@ import (
 )
 
 func defframe(ptxt *obj.Prog) {
-       var n *gc.Node
-
        // fill in argument size, stack size
        ptxt.To.Type = obj.TYPE_TEXTSIZE
 
@@ -30,8 +28,7 @@ func defframe(ptxt *obj.Prog) {
        lo := hi
 
        // iterate through declarations - they are sorted in decreasing xoffset order.
-       for l := gc.Curfn.Func.Dcl; l != nil; l = l.Next {
-               n = l.N
+       for _, n := range gc.Curfn.Func.Dcl {
                if !n.Name.Needzero {
                        continue
                }
index 00fcdb8443ee58313d3d73c3cb387f6cdd0910d7..5e50f9e0e8fe88dea65ab1ff7987ef94ee505d0e 100644 (file)
@@ -12,8 +12,6 @@ import (
 )
 
 func defframe(ptxt *obj.Prog) {
-       var n *gc.Node
-
        // fill in argument size, stack size
        ptxt.To.Type = obj.TYPE_TEXTSIZE
 
@@ -30,8 +28,7 @@ func defframe(ptxt *obj.Prog) {
        lo := hi
 
        // iterate through declarations - they are sorted in decreasing xoffset order.
-       for l := gc.Curfn.Func.Dcl; l != nil; l = l.Next {
-               n = l.N
+       for _, n := range gc.Curfn.Func.Dcl {
                if !n.Name.Needzero {
                        continue
                }
index 139b199b5788b6a85e28b46aaacc1501a08a3d11..480ae1c585d9e4fafbced11392fd330445746922 100644 (file)
@@ -11,8 +11,6 @@ import (
 )
 
 func defframe(ptxt *obj.Prog) {
-       var n *gc.Node
-
        // fill in argument size, stack size
        ptxt.To.Type = obj.TYPE_TEXTSIZE
 
@@ -28,8 +26,7 @@ func defframe(ptxt *obj.Prog) {
        hi := int64(0)
        lo := hi
        ax := uint32(0)
-       for l := gc.Curfn.Func.Dcl; l != nil; l = l.Next {
-               n = l.N
+       for _, n := range gc.Curfn.Func.Dcl {
                if !n.Name.Needzero {
                        continue
                }