From 20edeabc0fc73c6212769142f80e921c2e07ee08 Mon Sep 17 00:00:00 2001
From: Josh Bleecher Snyder <josharian@gmail.com>
Date: Thu, 27 Oct 2016 20:15:29 -0700
Subject: [PATCH] cmd/compile: don't alloc Name/Param for unresolved syms
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

ONONAME nodes generated from unresolved symbols don't need Params.
They only need Names to store Iota; move Iota to Node.Xoffset.
While we're here, change iota to int64 to reduce casting.

Passes toolstash -cmp.

name       old alloc/op     new alloc/op     delta
Template       39.9MB 卤 0%      39.7MB 卤 0%  -0.39%        (p=0.000 n=19+20)
Unicode        30.9MB 卤 0%      30.7MB 卤 0%  -0.35%        (p=0.000 n=20+20)
GoTypes         119MB 卤 0%       118MB 卤 0%  -0.42%        (p=0.000 n=20+20)
Compiler        464MB 卤 0%       461MB 卤 0%  -0.54%        (p=0.000 n=19+20)

name       old allocs/op    new allocs/op    delta
Template         386k 卤 0%        383k 卤 0%  -0.62%        (p=0.000 n=20+20)
Unicode          323k 卤 0%        321k 卤 0%  -0.49%        (p=0.000 n=20+20)
GoTypes         1.16M 卤 0%       1.15M 卤 0%  -0.67%        (p=0.000 n=20+20)
Compiler        4.09M 卤 0%       4.05M 卤 0%  -0.95%        (p=0.000 n=20+20)

Change-Id: Ib27219a0d0405def1b4dadacf64935ba12d10a94
Reviewed-on: https://go-review.googlesource.com/32237
Run-TryBot: Josh Bleecher Snyder <josharian@gmail.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Matthew Dempsky <mdempsky@google.com>
---
 src/cmd/compile/internal/gc/dcl.go         | 20 +++++++++++++++-----
 src/cmd/compile/internal/gc/go.go          |  2 +-
 src/cmd/compile/internal/gc/noder.go       |  2 +-
 src/cmd/compile/internal/gc/sizeof_test.go |  2 +-
 src/cmd/compile/internal/gc/subr.go        |  4 +---
 src/cmd/compile/internal/gc/syntax.go      | 10 +++++++++-
 src/cmd/compile/internal/gc/typecheck.go   |  4 ++--
 7 files changed, 30 insertions(+), 14 deletions(-)

diff --git a/src/cmd/compile/internal/gc/dcl.go b/src/cmd/compile/internal/gc/dcl.go
index c4b9ad0d92..d5c8fe071f 100644
--- a/src/cmd/compile/internal/gc/dcl.go
+++ b/src/cmd/compile/internal/gc/dcl.go
@@ -332,10 +332,21 @@ func newname(s *Sym) *Node {
 	if s == nil {
 		Fatalf("newname nil")
 	}
-
 	n := nod(ONAME, nil, nil)
 	n.Sym = s
-	n.Type = nil
+	n.Addable = true
+	n.Ullman = 1
+	n.Xoffset = 0
+	return n
+}
+
+// newnoname returns a new ONONAME Node associated with symbol s.
+func newnoname(s *Sym) *Node {
+	if s == nil {
+		Fatalf("newnoname nil")
+	}
+	n := nod(ONONAME, nil, nil)
+	n.Sym = s
 	n.Addable = true
 	n.Ullman = 1
 	n.Xoffset = 0
@@ -388,9 +399,8 @@ func oldname(s *Sym) *Node {
 		// Maybe a top-level declaration will come along later to
 		// define s. resolve will check s.Def again once all input
 		// source has been processed.
-		n = newname(s)
-		n.Op = ONONAME
-		n.Name.Iota = iota_ // save current iota value in const declarations
+		n = newnoname(s)
+		n.SetIota(iota_) // save current iota value in const declarations
 		return n
 	}
 
diff --git a/src/cmd/compile/internal/gc/go.go b/src/cmd/compile/internal/gc/go.go
index 8c05149618..089b6668b9 100644
--- a/src/cmd/compile/internal/gc/go.go
+++ b/src/cmd/compile/internal/gc/go.go
@@ -217,7 +217,7 @@ var dclcontext Class // PEXTERN/PAUTO
 
 var statuniqgen int // name generator for static temps
 
-var iota_ int32
+var iota_ int64
 
 var lastconst []*Node
 
diff --git a/src/cmd/compile/internal/gc/noder.go b/src/cmd/compile/internal/gc/noder.go
index f8056fee97..5e3206d6e6 100644
--- a/src/cmd/compile/internal/gc/noder.go
+++ b/src/cmd/compile/internal/gc/noder.go
@@ -52,7 +52,7 @@ func (p *noder) file(file *syntax.File) {
 func (p *noder) decls(decls []syntax.Decl) (l []*Node) {
 	var lastConstGroup *syntax.Group
 	var lastConstRHS []*Node
-	var iotaVal int32
+	var iotaVal int64
 
 	for _, decl := range decls {
 		p.lineno(decl)
diff --git a/src/cmd/compile/internal/gc/sizeof_test.go b/src/cmd/compile/internal/gc/sizeof_test.go
index eeddecf00e..22646552a1 100644
--- a/src/cmd/compile/internal/gc/sizeof_test.go
+++ b/src/cmd/compile/internal/gc/sizeof_test.go
@@ -23,7 +23,7 @@ func TestSizeof(t *testing.T) {
 		_64bit uintptr     // size on 64bit platforms
 	}{
 		{Func{}, 92, 160},
-		{Name{}, 48, 72},
+		{Name{}, 44, 72},
 		{Node{}, 92, 144},
 		{Sym{}, 60, 112},
 		{Type{}, 60, 96},
diff --git a/src/cmd/compile/internal/gc/subr.go b/src/cmd/compile/internal/gc/subr.go
index fafb8ffc1e..52e28bff94 100644
--- a/src/cmd/compile/internal/gc/subr.go
+++ b/src/cmd/compile/internal/gc/subr.go
@@ -504,9 +504,7 @@ func treecopy(n *Node, lineno int32) *Node {
 			if lineno != 0 {
 				m.Lineno = lineno
 			}
-			m.Name = new(Name)
-			*m.Name = *n.Name
-			m.Name.Iota = iota_
+			m.SetIota(iota_)
 			return &m
 		}
 		return n
diff --git a/src/cmd/compile/internal/gc/syntax.go b/src/cmd/compile/internal/gc/syntax.go
index 0be10c689b..5e635dd0cc 100644
--- a/src/cmd/compile/internal/gc/syntax.go
+++ b/src/cmd/compile/internal/gc/syntax.go
@@ -38,6 +38,7 @@ type Node struct {
 	// - ODOT, ODOTPTR, and OINDREGSP use it to indicate offset relative to their base address.
 	// - OSTRUCTKEY uses it to store the named field's offset.
 	// - OXCASE and OXFALL use it to validate the use of fallthrough.
+	// - ONONAME uses it to store the current value of iota, see Node.Iota
 	// Possibly still more uses. If you find any, document them.
 	Xoffset int64
 
@@ -162,6 +163,14 @@ func (n *Node) SetOpt(x interface{}) {
 	n.E = x
 }
 
+func (n *Node) Iota() int64 {
+	return n.Xoffset
+}
+
+func (n *Node) SetIota(x int64) {
+	n.Xoffset = x
+}
+
 // Name holds Node fields used only by named nodes (ONAME, OPACK, OLABEL, some OLITERAL).
 type Name struct {
 	Pack      *Node  // real package for import . names
@@ -172,7 +181,6 @@ type Name struct {
 	Param     *Param // additional fields for ONAME
 	Decldepth int32  // declaration loop depth, increased for every loop or label
 	Vargen    int32  // unique name for ONAME within a function.  Function outputs are numbered starting at one.
-	Iota      int32  // value if this name is iota
 	Funcdepth int32
 	Method    bool // OCALLMETH name
 	Readonly  bool
diff --git a/src/cmd/compile/internal/gc/typecheck.go b/src/cmd/compile/internal/gc/typecheck.go
index 866c387f41..039b447259 100644
--- a/src/cmd/compile/internal/gc/typecheck.go
+++ b/src/cmd/compile/internal/gc/typecheck.go
@@ -35,8 +35,8 @@ func resolve(n *Node) *Node {
 		if r != nil {
 			if r.Op != OIOTA {
 				n = r
-			} else if n.Name.Iota >= 0 {
-				n = nodintconst(int64(n.Name.Iota))
+			} else if n.Iota() >= 0 {
+				n = nodintconst(n.Iota())
 			}
 		}
 	}
-- 
2.30.9