]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/compile: change Func.{Enter,Exit} from NodeList to slice
authorIan Lance Taylor <iant@golang.org>
Fri, 26 Feb 2016 22:28:48 +0000 (14:28 -0800)
committerIan Lance Taylor <iant@golang.org>
Sat, 27 Feb 2016 00:59:47 +0000 (00:59 +0000)
Introduces a new types Nodes that can be used to replace NodeList.

Update #14473.

Change-Id: Id77c5dcae0cbeb898ba12dd46bd400aad408871c
Reviewed-on: https://go-review.googlesource.com/19969
Reviewed-by: David Crawshaw <crawshaw@golang.org>
Run-TryBot: Ian Lance Taylor <iant@golang.org>
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
src/cmd/compile/internal/gc/cgen.go
src/cmd/compile/internal/gc/closure.go
src/cmd/compile/internal/gc/fmt.go
src/cmd/compile/internal/gc/gen.go
src/cmd/compile/internal/gc/pgen.go
src/cmd/compile/internal/gc/racewalk.go
src/cmd/compile/internal/gc/syntax.go
src/cmd/compile/internal/gc/typecheck.go
src/cmd/compile/internal/gc/walk.go

index 7be050dd56651cd6308b7d7ee95f9636178e3e31..74f61129c260bda4b2d99dac11c1777184696061 100644 (file)
@@ -2621,7 +2621,7 @@ func cgen_ret(n *Node) {
        if hasdefer {
                Ginscall(Deferreturn, 0)
        }
-       Genlist(Curfn.Func.Exit)
+       Genslice(Curfn.Func.Exit.Slice())
        p := Thearch.Gins(obj.ARET, nil, nil)
        if n != nil && n.Op == ORETJMP {
                p.To.Type = obj.TYPE_MEM
index c8c59ef201dbc728dc7d9e4da260c1893e159d6f..401cd797dc3cee7322cda28f33a45a7e6bc96376 100644 (file)
@@ -223,7 +223,7 @@ func capturevars(xfunc *Node) {
        lineno = xfunc.Lineno
 
        func_ := xfunc.Func.Closure
-       func_.Func.Enter = nil
+       func_.Func.Enter.Set(nil)
        for _, v := range func_.Func.Cvars() {
                if v.Type == nil {
                        // if v->type is nil, it means v looked like it was
@@ -265,7 +265,7 @@ func capturevars(xfunc *Node) {
                }
 
                typecheck(&outer, Erv)
-               func_.Func.Enter = list(func_.Func.Enter, outer)
+               func_.Func.Enter.Append(outer)
        }
 
        lineno = int32(lno)
@@ -350,9 +350,7 @@ func transformclosure(xfunc *Node) {
                xfunc.Type = f.Type // update type of ODCLFUNC
        } else {
                // The closure is not called, so it is going to stay as closure.
-               nvar := 0
-
-               var body *NodeList
+               var body []*Node
                offset := int64(Widthptr)
                var addr *Node
                var cv *Node
@@ -360,7 +358,6 @@ func transformclosure(xfunc *Node) {
                        if v.Op == OXXX {
                                continue
                        }
-                       nvar++
 
                        // cv refers to the field inside of closure OSTRUCTLIT.
                        cv = Nod(OCLOSUREVAR, nil, nil)
@@ -378,7 +375,7 @@ func transformclosure(xfunc *Node) {
                                v.Class = PAUTO
                                v.Ullman = 1
                                xfunc.Func.Dcl = append(xfunc.Func.Dcl, v)
-                               body = list(body, Nod(OAS, v, cv))
+                               body = append(body, Nod(OAS, v, cv))
                        } else {
                                // Declare variable holding addresses taken from closure
                                // and initialize in entry prologue.
@@ -392,14 +389,16 @@ func transformclosure(xfunc *Node) {
                                if v.Name.Byval {
                                        cv = Nod(OADDR, cv, nil)
                                }
-                               body = list(body, Nod(OAS, addr, cv))
+                               body = append(body, Nod(OAS, addr, cv))
                        }
                }
 
-               typechecklist(body, Etop)
-               walkstmtlist(body)
-               xfunc.Func.Enter = body
-               xfunc.Func.Needctxt = nvar > 0
+               if len(body) > 0 {
+                       typecheckslice(body, Etop)
+                       walkstmtslice(body)
+                       xfunc.Func.Enter.Set(body)
+                       xfunc.Func.Needctxt = true
+               }
        }
 
        lineno = int32(lno)
@@ -443,7 +442,7 @@ func walkclosure(func_ *Node, init **NodeList) *Node {
        clos := Nod(OCOMPLIT, nil, Nod(OIND, typ, nil))
        clos.Esc = func_.Esc
        clos.Right.Implicit = true
-       clos.List = concat(list1(Nod(OCFUNC, func_.Func.Closure.Func.Nname, nil)), func_.Func.Enter)
+       clos.List = concat(list1(Nod(OCFUNC, func_.Func.Closure.Func.Nname, nil)), func_.Func.Enter.NodeList())
 
        // Force type conversion from *struct to the func type.
        clos = Nod(OCONVNOP, clos, nil)
index c0a1170839ab2a4704692ce37191d64dc95bdba2..9327a13d9160fbff7d893fdf943482ebf82daa21 100644 (file)
@@ -1729,10 +1729,42 @@ func Hconv(l *NodeList, flag int) string {
        return buf.String()
 }
 
+func Hconvslice(l []*Node, flag int) string {
+       if len(l) == 0 && fmtmode == FDbg {
+               return "<nil>"
+       }
+
+       sf := flag
+       sm, sb := setfmode(&flag)
+       sep := "; "
+       if fmtmode == FDbg {
+               sep = "\n"
+       } else if flag&obj.FmtComma != 0 {
+               sep = ", "
+       }
+
+       var buf bytes.Buffer
+       for i, n := range l {
+               buf.WriteString(Nconv(n, 0))
+               if i+1 < len(l) {
+                       buf.WriteString(sep)
+               }
+       }
+
+       flag = sf
+       fmtbody = sb
+       fmtmode = sm
+       return buf.String()
+}
+
 func dumplist(s string, l *NodeList) {
        fmt.Printf("%s%v\n", s, Hconv(l, obj.FmtSign))
 }
 
+func dumpslice(s string, l []*Node) {
+       fmt.Printf("%s%v\n", s, Hconvslice(l, obj.FmtSign))
+}
+
 func Dump(s string, n *Node) {
        fmt.Printf("%s [%p]%v\n", s, n, Nconv(n, obj.FmtSign))
 }
index adebfb81d0f65ed5056bad407233eadd60ed74ee..4edef2b97abc900a62ce755496042dfe1abc90da 100644 (file)
@@ -219,6 +219,12 @@ func Genlist(l *NodeList) {
        }
 }
 
+func Genslice(l []*Node) {
+       for _, n := range l {
+               gen(n)
+       }
+}
+
 // generate code to start new proc running call n.
 func cgen_proc(n *Node, proc int) {
        switch n.Left.Op {
index 475d8e7b83c883c3a5f2dc2c024054016b9dca76..6c5fb2d35bb0efa9c510b5c51b04d7fcb7e3ea02 100644 (file)
@@ -471,7 +471,7 @@ func compile(fn *Node) {
                }
        }
 
-       Genlist(Curfn.Func.Enter)
+       Genslice(Curfn.Func.Enter.Slice())
        Genlist(Curfn.Nbody)
        gclean()
        checklabels()
index d1ae6be0ad058c7e2bc11fb37e340ccc68d586d7..d1f6cefec52a6984db49baba3e16ff00515d94d4 100644 (file)
@@ -58,7 +58,7 @@ func instrument(fn *Node) {
                instrumentlist(fn.Nbody, nil)
 
                // nothing interesting for race detector in fn->enter
-               instrumentlist(fn.Func.Exit, nil)
+               instrumentslice(fn.Func.Exit.Slice(), nil)
        }
 
        if flag_race != 0 {
@@ -71,18 +71,18 @@ func instrument(fn *Node) {
                nodpc.Type = Types[TUINTPTR]
                nodpc.Xoffset = int64(-Widthptr)
                nd := mkcall("racefuncenter", nil, nil, nodpc)
-               fn.Func.Enter = concat(list1(nd), fn.Func.Enter)
+               fn.Func.Enter.Set(append([]*Node{nd}, fn.Func.Enter.Slice()...))
                nd = mkcall("racefuncexit", nil, nil)
-               fn.Func.Exit = list(fn.Func.Exit, nd)
+               fn.Func.Exit.Append(nd)
        }
 
        if Debug['W'] != 0 {
                s := fmt.Sprintf("after instrument %v", fn.Func.Nname.Sym)
                dumplist(s, fn.Nbody)
                s = fmt.Sprintf("enter %v", fn.Func.Nname.Sym)
-               dumplist(s, fn.Func.Enter)
+               dumpslice(s, fn.Func.Enter.Slice())
                s = fmt.Sprintf("exit %v", fn.Func.Nname.Sym)
-               dumplist(s, fn.Func.Exit)
+               dumpslice(s, fn.Func.Exit.Slice())
        }
 }
 
@@ -100,6 +100,18 @@ func instrumentlist(l *NodeList, init **NodeList) {
        }
 }
 
+func instrumentslice(l []*Node, init **NodeList) {
+       for i := range l {
+               var instr *NodeList
+               instrumentnode(&l[i], &instr, 0, 0)
+               if init == nil {
+                       l[i].Ninit = concat(l[i].Ninit, instr)
+               } else {
+                       *init = concat(*init, instr)
+               }
+       }
+}
+
 // walkexpr and walkstmt combined
 // walks the tree and adds calls to the
 // instrumentation code to top-level (statement) nodes' init
index edc3f3ca10d2ae9beb20ba35aed1bf3daac6dd1a..4e988360f10b85e39f31a96cb99dd5d7b1656611 100644 (file)
@@ -149,8 +149,8 @@ type Param struct {
 // Func holds Node fields used only with function-like nodes.
 type Func struct {
        Shortname  *Node
-       Enter      *NodeList
-       Exit       *NodeList
+       Enter      Nodes
+       Exit       Nodes
        cvars      *[]*Node // closure params
        Dcl        []*Node  // autodcl for this func/closure
        Inldcl     *[]*Node // copy of dcl for use in inlining
@@ -506,3 +506,55 @@ func count(l *NodeList) int {
        }
        return int(n)
 }
+
+// Nodes is a pointer to a slice of *Node.
+// For fields that are not used in most nodes, this is used instead of
+// a slice to save space.
+type Nodes struct{ slice *[]*Node }
+
+// Slice returns the entries in Nodes as a slice.
+// Changes to the slice entries (as in s[i] = n) will be reflected in
+// the Nodes.
+func (n *Nodes) Slice() []*Node {
+       if n.slice == nil {
+               return nil
+       }
+       return *n.slice
+}
+
+// NodeList returns the entries in Nodes as a NodeList.
+// Changes to the NodeList entries (as in l.N = n) will *not* be
+// reflect in the Nodes.
+// This wastes memory and should be used as little as possible.
+func (n *Nodes) NodeList() *NodeList {
+       if n.slice == nil {
+               return nil
+       }
+       var ret *NodeList
+       for _, n := range *n.slice {
+               ret = list(ret, n)
+       }
+       return ret
+}
+
+// Set sets Nodes to a slice.
+// This takes ownership of the slice.
+func (n *Nodes) Set(s []*Node) {
+       if len(s) == 0 {
+               n.slice = nil
+       } else {
+               n.slice = &s
+       }
+}
+
+// Append appends entries to Nodes.
+// If a slice is passed in, this will take ownership of it.
+func (n *Nodes) Append(a ...*Node) {
+       if n.slice == nil {
+               if len(a) > 0 {
+                       n.slice = &a
+               }
+       } else {
+               *n.slice = append(*n.slice, a...)
+       }
+}
index 395f04c21b5492c96687ff4d6c69da6620592ac8..04455515e61e69a10c701c4b01e148df8b8c63f5 100644 (file)
@@ -40,6 +40,12 @@ func typechecklist(l *NodeList, top int) {
        }
 }
 
+func typecheckslice(l []*Node, top int) {
+       for i := range l {
+               typecheck(&l[i], top)
+       }
+}
+
 var _typekind = []string{
        TINT:        "int",
        TUINT:       "uint",
index acc923a866883438bcd213c88581b3e749666e76..5e1db64df4dc5db786e97278f37f207e5f70d480 100644 (file)
@@ -71,9 +71,9 @@ func walk(fn *Node) {
        }
 
        heapmoves()
-       if Debug['W'] != 0 && Curfn.Func.Enter != nil {
+       if Debug['W'] != 0 && len(Curfn.Func.Enter.Slice()) > 0 {
                s := fmt.Sprintf("enter %v", Curfn.Func.Nname.Sym)
-               dumplist(s, Curfn.Func.Enter)
+               dumpslice(s, Curfn.Func.Enter.Slice())
        }
 }
 
@@ -83,6 +83,12 @@ func walkstmtlist(l *NodeList) {
        }
 }
 
+func walkstmtslice(l []*Node) {
+       for i := range l {
+               walkstmt(&l[i])
+       }
+}
+
 func samelist(a *NodeList, b *NodeList) bool {
        for ; a != nil && b != nil; a, b = a.Next, b.Next {
                if a.N != b.N {
@@ -320,7 +326,7 @@ func walkstmt(np **Node) {
                        ll := ascompatee(n.Op, rl, n.List, &n.Ninit)
                        n.List = reorder3(ll)
                        for lr := n.List; lr != nil; lr = lr.Next {
-                               lr.N = applywritebarrier(lr.N, &n.Ninit)
+                               lr.N = applywritebarrier(lr.N)
                        }
                        break
                }
@@ -588,9 +594,9 @@ opswitch:
                        // transformclosure already did all preparation work.
 
                        // Prepend captured variables to argument list.
-                       n.List = concat(n.Left.Func.Enter, n.List)
+                       n.List = concat(n.Left.Func.Enter.NodeList(), n.List)
 
-                       n.Left.Func.Enter = nil
+                       n.Left.Func.Enter.Set(nil)
 
                        // Replace OCLOSURE with ONAME/PFUNC.
                        n.Left = n.Left.Func.Closure.Func.Nname
@@ -724,7 +730,7 @@ opswitch:
                        r := convas(Nod(OAS, n.Left, n.Right), init)
                        r.Dodata = n.Dodata
                        n = r
-                       n = applywritebarrier(n, init)
+                       n = applywritebarrier(n)
                }
 
        case OAS2:
@@ -735,7 +741,7 @@ opswitch:
                ll := ascompatee(OAS, n.List, n.Rlist, init)
                ll = reorder3(ll)
                for lr := ll; lr != nil; lr = lr.Next {
-                       lr.N = applywritebarrier(lr.N, init)
+                       lr.N = applywritebarrier(lr.N)
                }
                n = liststmt(ll)
 
@@ -750,7 +756,7 @@ opswitch:
 
                ll := ascompatet(n.Op, n.List, &r.Type, 0, init)
                for lr := ll; lr != nil; lr = lr.Next {
-                       lr.N = applywritebarrier(lr.N, init)
+                       lr.N = applywritebarrier(lr.N)
                }
                n = liststmt(concat(list1(r), ll))
 
@@ -2133,7 +2139,7 @@ func needwritebarrier(l *Node, r *Node) bool {
 
 // TODO(rsc): Perhaps componentgen should run before this.
 
-func applywritebarrier(n *Node, init **NodeList) *Node {
+func applywritebarrier(n *Node) *Node {
        if n.Left != nil && n.Right != nil && needwritebarrier(n.Left, n.Right) {
                if Debug_wb > 1 {
                        Warnl(int(n.Lineno), "marking %v for barrier", Nconv(n.Left, 0))
@@ -2542,12 +2548,12 @@ func vmatch1(l *Node, r *Node) bool {
 // walk through argin parameters.
 // generate and return code to allocate
 // copies of escaped parameters to the heap.
-func paramstoheap(argin **Type, out int) *NodeList {
+func paramstoheap(argin **Type, out int) []*Node {
        var savet Iter
        var v *Node
        var as *Node
 
-       var nn *NodeList
+       var nn []*Node
        for t := Structfirst(&savet, argin); t != nil; t = structnext(&savet) {
                v = t.Nname
                if v != nil && v.Sym != nil && v.Sym.Name[0] == '~' && v.Sym.Name[1] == 'r' { // unnamed result
@@ -2560,7 +2566,7 @@ func paramstoheap(argin **Type, out int) *NodeList {
                        // Defer might stop a panic and show the
                        // return values as they exist at the time of panic.
                        // Make sure to zero them on entry to the function.
-                       nn = list(nn, Nod(OAS, nodarg(t, 1), nil))
+                       nn = append(nn, Nod(OAS, nodarg(t, 1), nil))
                }
 
                if v == nil || v.Class&PHEAP == 0 {
@@ -2574,13 +2580,13 @@ func paramstoheap(argin **Type, out int) *NodeList {
                if prealloc[v] == nil {
                        prealloc[v] = callnew(v.Type)
                }
-               nn = list(nn, Nod(OAS, v.Name.Heapaddr, prealloc[v]))
+               nn = append(nn, Nod(OAS, v.Name.Heapaddr, prealloc[v]))
                if v.Class&^PHEAP != PPARAMOUT {
                        as = Nod(OAS, v, v.Name.Param.Stackparam)
                        v.Name.Param.Stackparam.Typecheck = 1
                        typecheck(&as, Etop)
-                       as = applywritebarrier(as, &nn)
-                       nn = list(nn, as)
+                       as = applywritebarrier(as)
+                       nn = append(nn, as)
                }
        }
 
@@ -2588,17 +2594,17 @@ func paramstoheap(argin **Type, out int) *NodeList {
 }
 
 // walk through argout parameters copying back to stack
-func returnsfromheap(argin **Type) *NodeList {
+func returnsfromheap(argin **Type) []*Node {
        var savet Iter
        var v *Node
 
-       var nn *NodeList
+       var nn []*Node
        for t := Structfirst(&savet, argin); t != nil; t = structnext(&savet) {
                v = t.Nname
                if v == nil || v.Class != PHEAP|PPARAMOUT {
                        continue
                }
-               nn = list(nn, Nod(OAS, v.Name.Param.Stackparam, v))
+               nn = append(nn, Nod(OAS, v.Name.Param.Stackparam, v))
        }
 
        return nn
@@ -2611,11 +2617,11 @@ func heapmoves() {
        lno := lineno
        lineno = Curfn.Lineno
        nn := paramstoheap(getthis(Curfn.Type), 0)
-       nn = concat(nn, paramstoheap(getinarg(Curfn.Type), 0))
-       nn = concat(nn, paramstoheap(Getoutarg(Curfn.Type), 1))
-       Curfn.Func.Enter = concat(Curfn.Func.Enter, nn)
+       nn = append(nn, paramstoheap(getinarg(Curfn.Type), 0)...)
+       nn = append(nn, paramstoheap(Getoutarg(Curfn.Type), 1)...)
+       Curfn.Func.Enter.Append(nn...)
        lineno = Curfn.Func.Endlineno
-       Curfn.Func.Exit = returnsfromheap(Getoutarg(Curfn.Type))
+       Curfn.Func.Exit.Append(returnsfromheap(Getoutarg(Curfn.Type))...)
        lineno = lno
 }