cmd/compile: remove Node.Escflowsrc, Node.Escretval, Node.Escloopdepth, Node.Esclevel

$ sizeof -p cmd/compile/internal/gc Node
Node 200
$

Change-Id: Iba4e88eac6bee3e2349e818a5a2326deabcb96f9
Reviewed-on: https://go-review.googlesource.com/10528
Reviewed-by: Ian Lance Taylor <iant@golang.org>
Reviewed-by: Josh Bleecher Snyder <josharian@gmail.com>
diff --git a/src/cmd/compile/internal/gc/esc.go b/src/cmd/compile/internal/gc/esc.go
index ffbfc0d..76fb4d1 100644
--- a/src/cmd/compile/internal/gc/esc.go
+++ b/src/cmd/compile/internal/gc/esc.go
@@ -317,6 +317,26 @@
 	return int(l.suffixValue)
 }
 
+type NodeEscState struct {
+	Escflowsrc   *NodeList // flow(this, src)
+	Escretval    *NodeList // on OCALLxxx, list of dummy return values
+	Escloopdepth int32     // -1: global, 0: return variables, 1:function top level, increased inside function for every loop or label to mark scopes
+	Esclevel     Level
+}
+
+func (e *EscState) nodeEscState(n *Node) *NodeEscState {
+	if nE, ok := n.Opt.(*NodeEscState); ok {
+		return nE
+	}
+	if n.Opt != nil {
+		Fatal("nodeEscState: opt in use (%T)", n.Opt)
+	}
+	nE := new(NodeEscState)
+	n.Opt = nE
+	e.opts = append(e.opts, n)
+	return nE
+}
+
 // Escape constants are numbered in order of increasing "escapiness"
 // to help make inferences be monotonic.  With the exception of
 // EscNever which is sticky, eX < eY means that eY is more exposed
@@ -382,6 +402,7 @@
 	edgecount int       // diagnostic
 	noesc     *NodeList // list of possible non-escaping nodes, for printing
 	recursive bool      // recursive function or group of mutually recursive functions.
+	opts      []*Node   // nodes with .Opt initialized
 }
 
 // funcSym returns n.Nname.Sym if no nils are encountered along the way.
@@ -404,7 +425,7 @@
 	e.theSink.Orig = &e.theSink
 	e.theSink.Class = PEXTERN
 	e.theSink.Sym = Lookup(".sink")
-	e.theSink.Escloopdepth = -1
+	e.nodeEscState(&e.theSink).Escloopdepth = -1
 	e.recursive = recursive
 
 	for l := all; l != nil; l = l.Next {
@@ -442,11 +463,13 @@
 			}
 		}
 	}
+	for _, x := range e.opts {
+		x.Opt = nil
+	}
 }
 
 func escfunc(e *EscState, func_ *Node) {
 	//	print("escfunc %N %s\n", func->nname, e->recursive?"(recursive)":"");
-
 	if func_.Esc != 1 {
 		Fatal("repeat escfunc %v", func_.Nname)
 	}
@@ -461,13 +484,14 @@
 		if ll.N.Op != ONAME {
 			continue
 		}
+		llNE := e.nodeEscState(ll.N)
 		switch ll.N.Class {
 		// out params are in a loopdepth between the sink and all local variables
 		case PPARAMOUT:
-			ll.N.Escloopdepth = 0
+			llNE.Escloopdepth = 0
 
 		case PPARAM:
-			ll.N.Escloopdepth = 1
+			llNE.Escloopdepth = 1
 			if ll.N.Type != nil && !haspointers(ll.N.Type) {
 				break
 			}
@@ -575,13 +599,14 @@
 
 			// ll->n->nname is the variable per case
 			if ll.N.Nname != nil {
-				ll.N.Nname.Escloopdepth = e.loopdepth
+				e.nodeEscState(ll.N.Nname).Escloopdepth = e.loopdepth
 			}
 		}
 	}
 
 	// Big stuff escapes unconditionally
 	// "Big" conditions that were scattered around in walk have been gathered here
+	nE := e.nodeEscState(n)
 	if n.Esc != EscHeap && n.Type != nil && (n.Type.Width > MaxStackVarSize ||
 		n.Op == ONEW && n.Type.Type.Width >= 1<<16 ||
 		n.Op == OMAKESLICE && !isSmallMakeSlice(n)) {
@@ -611,7 +636,7 @@
 	// Record loop depth at declaration.
 	case ODCL:
 		if n.Left != nil {
-			n.Left.Escloopdepth = e.loopdepth
+			e.nodeEscState(n.Left).Escloopdepth = e.loopdepth
 		}
 
 	case OLABEL:
@@ -638,7 +663,7 @@
 			if Isfixedarray(n.Type) {
 				escassign(e, n.List.Next.N, n.Right)
 			} else {
-				escassign(e, n.List.Next.N, addDereference(n.Right))
+				escassign(e, n.List.Next.N, e.addDereference(n.Right))
 			}
 		}
 
@@ -726,7 +751,7 @@
 
 		// esccall already done on n->rlist->n. tie it's escretval to n->list
 	case OAS2FUNC: // x,y = f()
-		lr := n.Rlist.N.Escretval
+		lr := e.nodeEscState(n.Rlist.N).Escretval
 
 		var ll *NodeList
 		for ll = n.List; lr != nil && ll != nil; lr, ll = lr.Next, ll.Next {
@@ -742,7 +767,7 @@
 			// OAS2FUNC in disguise
 			// esccall already done on n->list->n
 			// tie n->list->n->escretval to curfn->dcl PPARAMOUT's
-			ll = n.List.N.Escretval
+			ll = e.nodeEscState(n.List.N).Escretval
 		}
 
 		for lr := Curfn.Func.Dcl; lr != nil && ll != nil; lr = lr.Next {
@@ -769,12 +794,12 @@
 		} else {
 			// append(slice1, slice2...) -- slice2 itself does not escape, but contents do.
 			slice2 := n.List.Next.N
-			escassign(e, &e.theSink, addDereference(slice2)) // lose track of assign of dereference
+			escassign(e, &e.theSink, e.addDereference(slice2)) // lose track of assign of dereference
 			if Debug['m'] > 2 {
 				Warnl(int(n.Lineno), "%v special treatment of append(slice1, slice2...) %v", curfnSym(n), Nconv(n, obj.FmtShort))
 			}
 		}
-		escassign(e, &e.theSink, addDereference(n.List.N)) // The original elements are now leaked, too
+		escassign(e, &e.theSink, e.addDereference(n.List.N)) // The original elements are now leaked, too
 
 	case OCONV, OCONVNOP:
 		escassign(e, n, n.Left)
@@ -782,7 +807,7 @@
 	case OCONVIFACE:
 		n.Esc = EscNone // until proven otherwise
 		e.noesc = list(e.noesc, n)
-		n.Escloopdepth = e.loopdepth
+		nE.Escloopdepth = e.loopdepth
 		escassign(e, n, n.Left)
 
 	case OARRAYLIT:
@@ -790,7 +815,7 @@
 			// Slice itself is not leaked until proven otherwise
 			n.Esc = EscNone
 			e.noesc = list(e.noesc, n)
-			n.Escloopdepth = e.loopdepth
+			nE.Escloopdepth = e.loopdepth
 		}
 
 		// Link values to array/slice
@@ -807,7 +832,7 @@
 	case OPTRLIT:
 		n.Esc = EscNone // until proven otherwise
 		e.noesc = list(e.noesc, n)
-		n.Escloopdepth = e.loopdepth
+		nE.Escloopdepth = e.loopdepth
 
 		// Link OSTRUCTLIT to OPTRLIT; if OPTRLIT escapes, OSTRUCTLIT elements do too.
 		escassign(e, n, n.Left)
@@ -815,7 +840,7 @@
 	case OCALLPART:
 		n.Esc = EscNone // until proven otherwise
 		e.noesc = list(e.noesc, n)
-		n.Escloopdepth = e.loopdepth
+		nE.Escloopdepth = e.loopdepth
 
 		// Contents make it to memory, lose track.
 		escassign(e, &e.theSink, n.Left)
@@ -823,7 +848,7 @@
 	case OMAPLIT:
 		n.Esc = EscNone // until proven otherwise
 		e.noesc = list(e.noesc, n)
-		n.Escloopdepth = e.loopdepth
+		nE.Escloopdepth = e.loopdepth
 
 		// Keys and values make it to memory, lose track.
 		for ll := n.List; ll != nil; ll = ll.Next {
@@ -844,7 +869,7 @@
 			if !v.Name.Byval {
 				a = Nod(OADDR, a, nil)
 				a.Lineno = v.Lineno
-				a.Escloopdepth = e.loopdepth
+				e.nodeEscState(a).Escloopdepth = e.loopdepth
 				typecheck(&a, Erv)
 			}
 
@@ -861,13 +886,13 @@
 		OSTRARRAYRUNE,
 		OSTRARRAYBYTE,
 		ORUNESTR:
-		n.Escloopdepth = e.loopdepth
+		nE.Escloopdepth = e.loopdepth
 
 		n.Esc = EscNone // until proven otherwise
 		e.noesc = list(e.noesc, n)
 
 	case OADDSTR:
-		n.Escloopdepth = e.loopdepth
+		nE.Escloopdepth = e.loopdepth
 		n.Esc = EscNone // until proven otherwise
 		e.noesc = list(e.noesc, n)
 
@@ -879,7 +904,7 @@
 
 		// current loop depth is an upper bound on actual loop depth
 		// of addressed value.
-		n.Escloopdepth = e.loopdepth
+		nE.Escloopdepth = e.loopdepth
 
 		// for &x, use loop depth of x if known.
 		// it should always be known, but if not, be conservative
@@ -887,8 +912,9 @@
 		if n.Left.Op == ONAME {
 			switch n.Left.Class {
 			case PAUTO:
-				if n.Left.Escloopdepth != 0 {
-					n.Escloopdepth = n.Left.Escloopdepth
+				leftE := e.nodeEscState(n.Left)
+				if leftE.Escloopdepth != 0 {
+					nE.Escloopdepth = leftE.Escloopdepth
 				}
 
 				// PPARAM is loop depth 1 always.
@@ -898,7 +924,7 @@
 			// to another (or the same) result makes the
 			// first result move to the heap.
 			case PPARAM, PPARAMOUT:
-				n.Escloopdepth = 1
+				nE.Escloopdepth = 1
 			}
 		}
 	}
@@ -1003,14 +1029,14 @@
 		// insert OADDR to account for the additional indirection.
 		a := Nod(OADDR, src, nil)
 		a.Lineno = src.Lineno
-		a.Escloopdepth = src.Escloopdepth
+		e.nodeEscState(a).Escloopdepth = e.nodeEscState(src).Escloopdepth
 		a.Type = Ptrto(src.Type)
 		escflows(e, dst, a)
 
 	// Flowing multiple returns to a single dst happens when
 	// analyzing "go f(g())": here g() flows to sink (issue 4529).
 	case OCALLMETH, OCALLFUNC, OCALLINTER:
-		for ll := src.Escretval; ll != nil; ll = ll.Next {
+		for ll := e.nodeEscState(src).Escretval; ll != nil; ll = ll.Next {
 			escflows(e, dst, ll.N)
 		}
 
@@ -1192,7 +1218,7 @@
 	// If content inside parameter (reached via indirection)
 	// escapes to heap, mark as such.
 	if em&EscContentEscapes != 0 {
-		escassign(e, &e.theSink, addDereference(src))
+		escassign(e, &e.theSink, e.addDereference(src))
 	}
 
 	em0 := em
@@ -1206,7 +1232,7 @@
 		if embits > 0 {
 			n := src
 			for i := uint16(0); i < embits-1; i++ {
-				n = addDereference(n) // encode level>0 as indirections
+				n = e.addDereference(n) // encode level>0 as indirections
 			}
 			escassign(e, dsts.N, n)
 		}
@@ -1221,12 +1247,12 @@
 	return em0
 }
 
-// addDereference constructs a suitable OIND note applied to src.
+// e.addDereference constructs a suitable OIND note applied to src.
 // Because this is for purposes of escape accounting, not execution,
 // some semantically dubious node combinations are (currently) possible.
-func addDereference(n *Node) *Node {
+func (e *EscState) addDereference(n *Node) *Node {
 	ind := Nod(OIND, n, nil)
-	ind.Escloopdepth = n.Escloopdepth
+	e.nodeEscState(ind).Escloopdepth = e.nodeEscState(n).Escloopdepth
 	ind.Lineno = n.Lineno
 	t := n.Type
 	if Istype(t, Tptr) {
@@ -1275,7 +1301,8 @@
 
 func initEscretval(e *EscState, n *Node, fntype *Type) {
 	i := 0
-	n.Escretval = nil // Suspect this is not nil for indirect calls.
+	nE := e.nodeEscState(n)
+	nE.Escretval = nil // Suspect this is not nil for indirect calls.
 	for t := getoutargx(fntype).Type; t != nil; t = t.Down {
 		src := Nod(ONAME, nil, nil)
 		buf := fmt.Sprintf(".out%d", i)
@@ -1284,10 +1311,10 @@
 		src.Type = t.Type
 		src.Class = PAUTO
 		src.Curfn = Curfn
-		src.Escloopdepth = e.loopdepth
+		e.nodeEscState(src).Escloopdepth = e.loopdepth
 		src.Used = true
 		src.Lineno = n.Lineno
-		n.Escretval = list(n.Escretval, src)
+		nE.Escretval = list(nE.Escretval, src)
 	}
 }
 
@@ -1327,7 +1354,7 @@
 	if n.List != nil && n.List.Next == nil {
 		a := n.List.N
 		if a.Type.Etype == TSTRUCT && a.Type.Funarg != 0 { // f(g()).
-			ll = a.Escretval
+			ll = e.nodeEscState(a).Escretval
 		}
 	}
 
@@ -1353,6 +1380,7 @@
 		return
 	}
 
+	nE := e.nodeEscState(n)
 	if fn != nil && fn.Op == ONAME && fn.Class == PFUNC &&
 		fn.Name.Defn != nil && fn.Name.Defn.Nbody != nil && fn.Param.Ntype != nil && fn.Name.Defn.Esc < EscFuncTagged {
 		if Debug['m'] > 2 {
@@ -1361,13 +1389,13 @@
 
 		// function in same mutually recursive group.  Incorporate into flow graph.
 		//		print("esc local fn: %N\n", fn->ntype);
-		if fn.Name.Defn.Esc == EscFuncUnknown || n.Escretval != nil {
+		if fn.Name.Defn.Esc == EscFuncUnknown || nE.Escretval != nil {
 			Fatal("graph inconsistency")
 		}
 
 		// set up out list on this call node
 		for lr := fn.Param.Ntype.Rlist; lr != nil; lr = lr.Next {
-			n.Escretval = list(n.Escretval, lr.N.Left) // type.rlist ->  dclfield -> ONAME (PPARAMOUT)
+			nE.Escretval = list(nE.Escretval, lr.N.Left) // type.rlist ->  dclfield -> ONAME (PPARAMOUT)
 		}
 
 		// Receiver.
@@ -1386,7 +1414,8 @@
 				src.Type.Type = lr.N.Type.Type
 				src.Type.Bound = int64(count(ll))
 				src.Type = Ptrto(src.Type) // make pointer so it will be tracked
-				src.Escloopdepth = e.loopdepth
+				srcE := e.nodeEscState(src)
+				srcE.Escloopdepth = e.loopdepth
 				src.Lineno = n.Lineno
 				src.Esc = EscNone // until we find otherwise
 				e.noesc = list(e.noesc, src)
@@ -1413,7 +1442,7 @@
 	}
 
 	// Imported or completely analyzed function.  Use the escape tags.
-	if n.Escretval != nil {
+	if nE.Escretval != nil {
 		Fatal("esc already decorated call %v\n", Nconv(n, obj.FmtSign))
 	}
 
@@ -1431,7 +1460,7 @@
 		t := getthisx(fntype).Type
 		src := n.Left.Left
 		if haspointers(t.Type) {
-			escassignfromtag(e, t.Note, n.Escretval, src)
+			escassignfromtag(e, t.Note, nE.Escretval, src)
 		}
 	}
 
@@ -1440,8 +1469,8 @@
 		if t.Isddd && !n.Isddd {
 			// Introduce ODDDARG node to represent ... allocation.
 			src = Nod(ODDDARG, nil, nil)
-
-			src.Escloopdepth = e.loopdepth
+			srcE := e.nodeEscState(src)
+			srcE.Escloopdepth = e.loopdepth
 			src.Lineno = n.Lineno
 			src.Type = typ(TARRAY)
 			src.Type.Type = t.Type.Type
@@ -1453,7 +1482,7 @@
 		}
 
 		if haspointers(t.Type) {
-			if escassignfromtag(e, t.Note, n.Escretval, src) == EscNone && up.Op != ODEFER && up.Op != OPROC {
+			if escassignfromtag(e, t.Note, nE.Escretval, src) == EscNone && up.Op != ODEFER && up.Op != OPROC {
 				a := src
 				for a.Op == OCONVNOP {
 					a = a.Left
@@ -1510,14 +1539,15 @@
 		fmt.Printf("%v::flows:: %v <- %v\n", Ctxt.Line(int(lineno)), Nconv(dst, obj.FmtShort), Nconv(src, obj.FmtShort))
 	}
 
-	if dst.Escflowsrc == nil {
+	dstE := e.nodeEscState(dst)
+	if dstE.Escflowsrc == nil {
 		e.dsts = list(e.dsts, dst)
 		e.dstcount++
 	}
 
 	e.edgecount++
 
-	dst.Escflowsrc = list(dst.Escflowsrc, src)
+	dstE.Escflowsrc = list(dstE.Escflowsrc, src)
 }
 
 // Whenever we hit a reference node, the level goes up by one, and whenever
@@ -1538,11 +1568,12 @@
 		return
 	}
 
+	dstE := e.nodeEscState(dst)
 	if Debug['m'] > 1 {
-		fmt.Printf("\nescflood:%d: dst %v scope:%v[%d]\n", walkgen, Nconv(dst, obj.FmtShort), curfnSym(dst), dst.Escloopdepth)
+		fmt.Printf("\nescflood:%d: dst %v scope:%v[%d]\n", walkgen, Nconv(dst, obj.FmtShort), curfnSym(dst), dstE.Escloopdepth)
 	}
 
-	for l := dst.Escflowsrc; l != nil; l = l.Next {
+	for l := dstE.Escflowsrc; l != nil; l = l.Next {
 		walkgen++
 		escwalk(e, levelFrom(0), dst, l.N)
 	}
@@ -1556,29 +1587,30 @@
 }
 
 func escwalk(e *EscState, level Level, dst *Node, src *Node) {
-
+	srcE := e.nodeEscState(src)
 	if src.Walkgen == walkgen {
 		// Esclevels are vectors, do not compare as integers,
 		// and must use "min" of old and new to guarantee
 		// convergence.
-		level = level.min(src.Esclevel)
-		if level == src.Esclevel {
+		level = level.min(srcE.Esclevel)
+		if level == srcE.Esclevel {
 			return
 		}
 	}
 
 	src.Walkgen = walkgen
-	src.Esclevel = level
+	srcE.Esclevel = level
 
 	if Debug['m'] > 1 {
 		fmt.Printf("escwalk: level:%d depth:%d %.*s op=%v %v(%v) scope:%v[%d]\n",
-			level, e.pdepth, e.pdepth, "\t\t\t\t\t\t\t\t\t\t", Oconv(int(src.Op), 0), Nconv(src, obj.FmtShort), Jconv(src, obj.FmtShort), curfnSym(src), src.Escloopdepth)
+			level, e.pdepth, e.pdepth, "\t\t\t\t\t\t\t\t\t\t", Oconv(int(src.Op), 0), Nconv(src, obj.FmtShort), Jconv(src, obj.FmtShort), curfnSym(src), srcE.Escloopdepth)
 	}
 
 	e.pdepth++
 
 	// Input parameter flowing to output parameter?
 	var leaks bool
+	dstE := e.nodeEscState(dst)
 	if funcOutputAndInput(dst, src) && src.Esc&EscMask < EscScope && dst.Esc != EscHeap {
 		// This case handles:
 		// 1. return in
@@ -1610,11 +1642,11 @@
 		}
 	}
 
-	leaks = level.int() <= 0 && level.guaranteedDereference() <= 0 && dst.Escloopdepth < src.Escloopdepth
+	leaks = level.int() <= 0 && level.guaranteedDereference() <= 0 && dstE.Escloopdepth < srcE.Escloopdepth
 
 	switch src.Op {
 	case ONAME:
-		if src.Class == PPARAM && (leaks || dst.Escloopdepth < 0) && src.Esc&EscMask < EscScope {
+		if src.Class == PPARAM && (leaks || dstE.Escloopdepth < 0) && src.Esc&EscMask < EscScope {
 			if level.guaranteedDereference() > 0 {
 				src.Esc = escMax(EscContentEscapes|src.Esc, EscNone)
 				if Debug['m'] != 0 {
@@ -1622,7 +1654,7 @@
 						Warnl(int(src.Lineno), "leaking param content: %v", Nconv(src, obj.FmtShort))
 					} else {
 						Warnl(int(src.Lineno), "leaking param content: %v level=%v dst.eld=%v src.eld=%v dst=%v",
-							Nconv(src, obj.FmtShort), level, dst.Escloopdepth, src.Escloopdepth, Nconv(dst, obj.FmtShort))
+							Nconv(src, obj.FmtShort), level, dstE.Escloopdepth, srcE.Escloopdepth, Nconv(dst, obj.FmtShort))
 					}
 				}
 			} else {
@@ -1632,7 +1664,7 @@
 						Warnl(int(src.Lineno), "leaking param: %v", Nconv(src, obj.FmtShort))
 					} else {
 						Warnl(int(src.Lineno), "leaking param: %v level=%v dst.eld=%v src.eld=%v dst=%v",
-							Nconv(src, obj.FmtShort), level, dst.Escloopdepth, src.Escloopdepth, Nconv(dst, obj.FmtShort))
+							Nconv(src, obj.FmtShort), level, dstE.Escloopdepth, srcE.Escloopdepth, Nconv(dst, obj.FmtShort))
 					}
 				}
 			}
@@ -1658,7 +1690,7 @@
 				}
 				if Debug['m'] > 1 {
 					Warnl(int(src.Lineno), "%v escapes to heap, level=%v, dst.eld=%v, src.eld=%v",
-						Nconv(p, obj.FmtShort), level, dst.Escloopdepth, src.Escloopdepth)
+						Nconv(p, obj.FmtShort), level, dstE.Escloopdepth, srcE.Escloopdepth)
 				} else {
 					Warnl(int(src.Lineno), "%v escapes to heap", Nconv(p, obj.FmtShort))
 				}
@@ -1726,19 +1758,20 @@
 	// See e.g. #10466
 	// This can only happen with functions returning a single result.
 	case OCALLMETH, OCALLFUNC, OCALLINTER:
-		if src.Escretval != nil {
+		if srcE.Escretval != nil {
 			if Debug['m'] > 1 {
 				fmt.Printf("%v:[%d] dst %v escwalk replace src: %v with %v\n",
 					Ctxt.Line(int(lineno)), e.loopdepth,
-					Nconv(dst, obj.FmtShort), Nconv(src, obj.FmtShort), Nconv(src.Escretval.N, obj.FmtShort))
+					Nconv(dst, obj.FmtShort), Nconv(src, obj.FmtShort), Nconv(srcE.Escretval.N, obj.FmtShort))
 			}
-			src = src.Escretval.N
+			src = srcE.Escretval.N
+			srcE = e.nodeEscState(src)
 		}
 	}
 
 recurse:
 	level = level.copy()
-	for ll := src.Escflowsrc; ll != nil; ll = ll.Next {
+	for ll := srcE.Escflowsrc; ll != nil; ll = ll.Next {
 		escwalk(e, level, dst, ll.N)
 	}
 
diff --git a/src/cmd/compile/internal/gc/fmt.go b/src/cmd/compile/internal/gc/fmt.go
index e3446f2..95181ac 100644
--- a/src/cmd/compile/internal/gc/fmt.go
+++ b/src/cmd/compile/internal/gc/fmt.go
@@ -259,8 +259,8 @@
 		fmt.Fprintf(&buf, " esc(%d)", n.Esc)
 	}
 
-	if n.Escloopdepth != 0 {
-		fmt.Fprintf(&buf, " ld(%d)", n.Escloopdepth)
+	if e, ok := n.Opt.(*NodeEscState); ok && e.Escloopdepth != 0 {
+		fmt.Fprintf(&buf, " ld(%d)", e.Escloopdepth)
 	}
 
 	if c == 0 && n.Typecheck != 0 {
diff --git a/src/cmd/compile/internal/gc/syntax.go b/src/cmd/compile/internal/gc/syntax.go
index 28756b7..a410cf4 100644
--- a/src/cmd/compile/internal/gc/syntax.go
+++ b/src/cmd/compile/internal/gc/syntax.go
@@ -33,10 +33,6 @@
 	Curfn *Node // function for local variables
 	Param *Param
 
-	// Escape analysis.
-	Escflowsrc *NodeList // flow(this, src)
-	Escretval  *NodeList // on OCALLxxx, list of dummy return values
-
 	Sym *Sym // various
 
 	Opt interface{} // for optimization passes
@@ -46,9 +42,6 @@
 
 	Xoffset int64
 
-	// Escape analysis.
-	Escloopdepth int32 // -1: global, 0: return variables, 1:function top level, increased inside function for every loop or label to mark scopes
-
 	Vargen  int32 // unique name for OTYPE/ONAME within a function.  Function outputs are numbered starting at one.
 	Lineno  int32
 	Iota    int32
@@ -59,9 +52,7 @@
 	// OREGISTER, OINDREG
 	Reg int16
 
-	// most nodes - smaller fields
-	Esclevel Level
-	Esc      uint16 // EscXXX
+	Esc uint16 // EscXXX
 
 	Op          uint8
 	Nointerface bool