diff --git a/src/cmd/compile/internal/gc/closure.go b/src/cmd/compile/internal/gc/closure.go index 6a3ee45a12..85c594787b 100644 --- a/src/cmd/compile/internal/gc/closure.go +++ b/src/cmd/compile/internal/gc/closure.go @@ -378,7 +378,7 @@ func closureType(clo ir.Node) *types.Type { return typ } -func walkclosure(clo ir.Node, init *ir.Nodes) ir.Node { +func walkclosure(clo *ir.ClosureExpr, init *ir.Nodes) ir.Node { fn := clo.Func() // If no closure vars, don't bother wrapping. @@ -403,12 +403,12 @@ func walkclosure(clo ir.Node, init *ir.Nodes) ir.Node { cfn := convnop(addr, clo.Type()) // non-escaping temp to use, if any. - if x := prealloc[clo]; x != nil { + if x := clo.Prealloc; x != nil { if !types.Identical(typ, x.Type()) { panic("closure type does not match order's assigned type") } addr.SetRight(x) - delete(prealloc, clo) + clo.Prealloc = nil } return walkexpr(cfn, init) @@ -552,12 +552,12 @@ func walkpartialcall(n *ir.CallPartExpr, init *ir.Nodes) ir.Node { cfn := convnop(addr, n.Type()) // non-escaping temp to use, if any. - if x := prealloc[n]; x != nil { + if x := n.Prealloc; x != nil { if !types.Identical(typ, x.Type()) { panic("partial call type does not match order's assigned type") } addr.SetRight(x) - delete(prealloc, n) + n.Prealloc = nil } return walkexpr(cfn, init) diff --git a/src/cmd/compile/internal/gc/order.go b/src/cmd/compile/internal/gc/order.go index 174037e30a..87d7cf3aa9 100644 --- a/src/cmd/compile/internal/gc/order.go +++ b/src/cmd/compile/internal/gc/order.go @@ -846,9 +846,9 @@ func (o *Order) stmt(n ir.Node) { r := n.Right() n.SetRight(o.copyExpr(r)) - // prealloc[n] is the temp for the iterator. + // n.Prealloc is the temp for the iterator. // hiter contains pointers and needs to be zeroed. - prealloc[n] = o.newTemp(hiter(n.Type()), true) + n.Prealloc = o.newTemp(hiter(n.Type()), true) } o.exprListInPlace(n.List()) if orderBody { @@ -1040,9 +1040,6 @@ func (o *Order) exprListInPlace(l ir.Nodes) { } } -// prealloc[x] records the allocation to use for x. -var prealloc = map[ir.Node]ir.Node{} - func (o *Order) exprNoLHS(n ir.Node) ir.Node { return o.expr(n, nil) } @@ -1079,11 +1076,12 @@ func (o *Order) expr1(n, lhs ir.Node) ir.Node { // Allocate a temporary to hold the strings. // Fewer than 5 strings use direct runtime helpers. case ir.OADDSTR: + n := n.(*ir.AddStringExpr) o.exprList(n.List()) if n.List().Len() > 5 { t := types.NewArray(types.Types[types.TSTRING], int64(n.List().Len())) - prealloc[n] = o.newTemp(t, false) + n.Prealloc = o.newTemp(t, false) } // Mark string(byteSlice) arguments to reuse byteSlice backing @@ -1268,7 +1266,7 @@ func (o *Order) expr1(n, lhs ir.Node) ir.Node { case ir.OCLOSURE: n := n.(*ir.ClosureExpr) if n.Transient() && len(n.Func().ClosureVars) > 0 { - prealloc[n] = o.newTemp(closureType(n), false) + n.Prealloc = o.newTemp(closureType(n), false) } return n @@ -1277,15 +1275,16 @@ func (o *Order) expr1(n, lhs ir.Node) ir.Node { n.SetLeft(o.expr(n.Left(), nil)) if n.Transient() { t := partialCallType(n) - prealloc[n] = o.newTemp(t, false) + n.Prealloc = o.newTemp(t, false) } return n case ir.OSLICELIT: + n := n.(*ir.CompLitExpr) o.exprList(n.List()) if n.Transient() { t := types.NewArray(n.Type().Elem(), ir.Int64Val(n.Right())) - prealloc[n] = o.newTemp(t, false) + n.Prealloc = o.newTemp(t, false) } return n diff --git a/src/cmd/compile/internal/gc/range.go b/src/cmd/compile/internal/gc/range.go index 90bee4fc74..aa4f0358c9 100644 --- a/src/cmd/compile/internal/gc/range.go +++ b/src/cmd/compile/internal/gc/range.go @@ -296,7 +296,7 @@ func walkrange(nrange *ir.RangeStmt) ir.Node { // we only use a once, so no copy needed. ha := a - hit := prealloc[nrange] + hit := nrange.Prealloc th := hit.Type() keysym := th.Field(0).Sym // depends on layout of iterator struct. See reflect.go:hiter elemsym := th.Field(1).Sym // ditto diff --git a/src/cmd/compile/internal/gc/sinit.go b/src/cmd/compile/internal/gc/sinit.go index e2c31e4dd7..7b710fd511 100644 --- a/src/cmd/compile/internal/gc/sinit.go +++ b/src/cmd/compile/internal/gc/sinit.go @@ -668,7 +668,7 @@ func slicelit(ctxt initContext, n *ir.CompLitExpr, var_ ir.Node, init *ir.Nodes) // set auto to point at new temp or heap (3 assign) var a ir.Node - if x := prealloc[n]; x != nil { + if x := n.Prealloc; x != nil { // temp allocated during order.go for dddarg if !types.Identical(t, x.Type()) { panic("dotdotdot base type does not match order's assigned type") diff --git a/src/cmd/compile/internal/gc/walk.go b/src/cmd/compile/internal/gc/walk.go index 23d1ce6003..a4ecc0c44d 100644 --- a/src/cmd/compile/internal/gc/walk.go +++ b/src/cmd/compile/internal/gc/walk.go @@ -202,10 +202,7 @@ func walkstmt(n ir.Node) ir.Node { if base.Flag.CompilingRuntime { base.Errorf("%v escapes to heap, not allowed in runtime", v) } - if prealloc[v] == nil { - prealloc[v] = callnew(v.Type()) - } - nn := ir.Nod(ir.OAS, v.Name().Heapaddr, prealloc[v]) + nn := ir.Nod(ir.OAS, v.Name().Heapaddr, callnew(v.Type())) nn.SetColas(true) return walkstmt(typecheck(nn, ctxStmt)) } @@ -1638,7 +1635,7 @@ func walkexpr1(n ir.Node, init *ir.Nodes) ir.Node { return mkcall1(chanfn("chansend1", 2, n.Left().Type()), nil, init, n.Left(), n1) case ir.OCLOSURE: - return walkclosure(n, init) + return walkclosure(n.(*ir.ClosureExpr), init) case ir.OCALLPART: return walkpartialcall(n.(*ir.CallPartExpr), init) @@ -2713,11 +2710,9 @@ func addstr(n *ir.AddStringExpr, init *ir.Nodes) ir.Node { fn = "concatstrings" t := types.NewSlice(types.Types[types.TSTRING]) - slice := ir.Nod(ir.OCOMPLIT, nil, ir.TypeNode(t)) - if prealloc[n] != nil { - prealloc[slice] = prealloc[n] - } - slice.PtrList().Set(args[1:]) // skip buf arg + // args[1:] to skip buf arg + slice := ir.NewCompLitExpr(base.Pos, ir.OCOMPLIT, ir.TypeNode(t), args[1:]) + slice.Prealloc = n.Prealloc args = []ir.Node{buf, slice} slice.SetEsc(EscNone) } diff --git a/src/cmd/compile/internal/ir/expr.go b/src/cmd/compile/internal/ir/expr.go index b18975d063..8f43eb0fb2 100644 --- a/src/cmd/compile/internal/ir/expr.go +++ b/src/cmd/compile/internal/ir/expr.go @@ -89,7 +89,8 @@ func toNtype(x Node) Ntype { // An AddStringExpr is a string concatenation Expr[0] + Exprs[1] + ... + Expr[len(Expr)-1]. type AddStringExpr struct { miniExpr - List_ Nodes + List_ Nodes + Prealloc *Name } func NewAddStringExpr(pos src.XPos, list []Node) *AddStringExpr { @@ -233,9 +234,10 @@ func (n *CallExpr) SetOp(op Op) { // A CallPartExpr is a method expression X.Method (uncalled). type CallPartExpr struct { miniExpr - Func_ *Func - X Node - Method *types.Field + Func_ *Func + X Node + Method *types.Field + Prealloc *Name } func NewCallPartExpr(pos src.XPos, x Node, method *types.Field, fn *Func) *CallPartExpr { @@ -255,7 +257,8 @@ func (n *CallPartExpr) SetLeft(x Node) { n.X = x } // A ClosureExpr is a function literal expression. type ClosureExpr struct { miniExpr - Func_ *Func + Func_ *Func + Prealloc *Name } func NewClosureExpr(pos src.XPos, fn *Func) *ClosureExpr { @@ -287,9 +290,10 @@ func (n *ClosureReadExpr) Offset() int64 { return n.Offset_ } // Before type-checking, the type is Ntype. type CompLitExpr struct { miniExpr - orig Node - Ntype Ntype - List_ Nodes // initialized values + orig Node + Ntype Ntype + List_ Nodes // initialized values + Prealloc *Name } func NewCompLitExpr(pos src.XPos, op Op, typ Ntype, list []Node) *CompLitExpr { diff --git a/src/cmd/compile/internal/ir/stmt.go b/src/cmd/compile/internal/ir/stmt.go index 4dd1733074..12811821ad 100644 --- a/src/cmd/compile/internal/ir/stmt.go +++ b/src/cmd/compile/internal/ir/stmt.go @@ -368,6 +368,7 @@ type RangeStmt struct { Body_ Nodes HasBreak_ bool typ *types.Type // TODO(rsc): Remove - use X.Type() instead + Prealloc *Name } func NewRangeStmt(pos src.XPos, vars []Node, x Node, body []Node) *RangeStmt {