From e59fe206e7aeaa8adad28f602d4361f8db2925a6 Mon Sep 17 00:00:00 2001 From: Matthew Dempsky Date: Wed, 27 Sep 2017 12:55:23 -0700 Subject: [PATCH] cmd/compile: mark closure structs as Noalg Avoids generating useless equality and hash functions. Shrinks cmd/go executable size on linux/amd64 by ~17kB. Change-Id: Ifde5315cc5cbceb3a7260195c8803cace952359f Reviewed-on: https://go-review.googlesource.com/66650 Run-TryBot: Matthew Dempsky TryBot-Result: Gobot Gobot Reviewed-by: Robert Griesemer --- src/cmd/compile/internal/gc/closure.go | 30 +++++++++++++++----------- src/cmd/compile/internal/gc/dcl.go | 6 +++++- 2 files changed, 22 insertions(+), 14 deletions(-) diff --git a/src/cmd/compile/internal/gc/closure.go b/src/cmd/compile/internal/gc/closure.go index afb6805337..93997b069a 100644 --- a/src/cmd/compile/internal/gc/closure.go +++ b/src/cmd/compile/internal/gc/closure.go @@ -480,28 +480,30 @@ func walkclosure(func_ *Node, init *Nodes) *Node { // the struct is unnamed so that closures in multiple packages with the // same struct type can share the descriptor. - typ := nod(OTSTRUCT, nil, nil) - - typ.List.Set1(namedfield(".F", types.Types[TUINTPTR])) + fields := []*Node{ + namedfield(".F", types.Types[TUINTPTR]), + } for _, v := range func_.Func.Cvars.Slice() { if v.Op == OXXX { continue } - typ1 := typenod(v.Type) + typ := v.Type if !v.Name.Byval() { - typ1 = nod(OIND, typ1, nil) + typ = types.NewPtr(typ) } - typ.List.Append(nod(ODCLFIELD, newname(v.Sym), typ1)) + fields = append(fields, symfield(v.Sym, typ)) } + typ := tostruct(fields) + typ.SetNoalg(true) + typ.SetLocal(true) - clos := nod(OCOMPLIT, nil, nod(OIND, typ, nil)) + clos := nod(OCOMPLIT, nil, nod(OIND, typenod(typ), nil)) clos.Esc = func_.Esc clos.Right.SetImplicit(true) clos.List.Set(append([]*Node{nod(OCFUNC, func_.Func.Closure.Func.Nname, nil)}, func_.Func.Enter.Slice()...)) // Force type conversion from *struct to the func type. clos = nod(OCONVNOP, clos, nil) - clos.Type = func_.Type clos = typecheck(clos, Erv) @@ -682,11 +684,14 @@ func walkpartialcall(n *Node, init *Nodes) *Node { checknil(n.Left, init) } - typ := nod(OTSTRUCT, nil, nil) - typ.List.Set1(namedfield("F", types.Types[TUINTPTR])) - typ.List.Append(namedfield("R", n.Left.Type)) + typ := tostruct([]*Node{ + namedfield("F", types.Types[TUINTPTR]), + namedfield("R", n.Left.Type), + }) + typ.SetNoalg(true) + typ.SetLocal(true) - clos := nod(OCOMPLIT, nil, nod(OIND, typ, nil)) + clos := nod(OCOMPLIT, nil, nod(OIND, typenod(typ), nil)) clos.Esc = n.Esc clos.Right.SetImplicit(true) clos.List.Set1(nod(OCFUNC, n.Func.Nname, nil)) @@ -694,7 +699,6 @@ func walkpartialcall(n *Node, init *Nodes) *Node { // Force type conversion from *struct to the func type. clos = nod(OCONVNOP, clos, nil) - clos.Type = n.Type clos = typecheck(clos, Erv) diff --git a/src/cmd/compile/internal/gc/dcl.go b/src/cmd/compile/internal/gc/dcl.go index cf91f53709..37d281d106 100644 --- a/src/cmd/compile/internal/gc/dcl.go +++ b/src/cmd/compile/internal/gc/dcl.go @@ -254,7 +254,11 @@ func anonfield(typ *types.Type) *Node { } func namedfield(s string, typ *types.Type) *Node { - return nod(ODCLFIELD, newname(lookup(s)), typenod(typ)) + return symfield(lookup(s), typ) +} + +func symfield(s *types.Sym, typ *types.Type) *Node { + return nod(ODCLFIELD, newname(s), typenod(typ)) } // oldname returns the Node that declares symbol s in the current scope. -- 2.48.1