2015-02-13 14:40:36 -05:00
|
|
|
// Copyright 2009 The Go Authors. All rights reserved.
|
|
|
|
|
// Use of this source code is governed by a BSD-style
|
|
|
|
|
// license that can be found in the LICENSE file.
|
|
|
|
|
|
|
|
|
|
package gc
|
|
|
|
|
|
|
|
|
|
import (
|
|
|
|
|
"fmt"
|
|
|
|
|
)
|
|
|
|
|
|
2015-10-22 09:51:12 +09:00
|
|
|
// static initialization
|
2015-02-13 14:40:36 -05:00
|
|
|
const (
|
|
|
|
|
InitNotStarted = 0
|
|
|
|
|
InitDone = 1
|
|
|
|
|
InitPending = 2
|
|
|
|
|
)
|
|
|
|
|
|
2016-03-11 00:44:39 -08:00
|
|
|
type InitEntry struct {
|
|
|
|
|
Xoffset int64 // struct, array only
|
|
|
|
|
Expr *Node // bytes of run-time computed expressions
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
type InitPlan struct {
|
2016-03-13 17:48:17 -07:00
|
|
|
E []InitEntry
|
2016-03-11 00:44:39 -08:00
|
|
|
}
|
|
|
|
|
|
2015-06-03 14:16:01 -04:00
|
|
|
var (
|
2015-09-03 17:07:00 +10:00
|
|
|
initlist []*Node
|
2015-06-03 14:16:01 -04:00
|
|
|
initplans map[*Node]*InitPlan
|
|
|
|
|
inittemps = make(map[*Node]*Node)
|
|
|
|
|
)
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
|
// init1 walks the AST starting at n, and accumulates in out
|
|
|
|
|
// the list of definitions needing init code in dependency order.
|
2016-02-27 14:31:33 -08:00
|
|
|
func init1(n *Node, out *[]*Node) {
|
2015-02-13 14:40:36 -05:00
|
|
|
if n == nil {
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
init1(n.Left, out)
|
|
|
|
|
init1(n.Right, out)
|
2016-03-08 15:10:26 -08:00
|
|
|
for _, n1 := range n.List.Slice() {
|
|
|
|
|
init1(n1, out)
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if n.Left != nil && n.Type != nil && n.Left.Op == OTYPE && n.Class == PFUNC {
|
|
|
|
|
// Methods called as Type.Method(receiver, ...).
|
|
|
|
|
// Definitions for method expressions are stored in type->nname.
|
2016-03-30 16:59:53 -07:00
|
|
|
init1(n.Type.Nname(), out)
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if n.Op != ONAME {
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
switch n.Class {
|
2015-04-01 09:38:44 -07:00
|
|
|
case PEXTERN, PFUNC:
|
2015-02-13 14:40:36 -05:00
|
|
|
default:
|
2015-05-27 07:31:56 -04:00
|
|
|
if isblank(n) && n.Name.Curfn == nil && n.Name.Defn != nil && n.Name.Defn.Initorder == InitNotStarted {
|
2015-02-13 14:40:36 -05:00
|
|
|
// blank names initialization is part of init() but not
|
|
|
|
|
// when they are inside a function.
|
|
|
|
|
break
|
|
|
|
|
}
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if n.Initorder == InitDone {
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
if n.Initorder == InitPending {
|
|
|
|
|
// Since mutually recursive sets of functions are allowed,
|
|
|
|
|
// we don't necessarily raise an error if n depends on a node
|
|
|
|
|
// which is already waiting for its dependencies to be visited.
|
|
|
|
|
//
|
|
|
|
|
// initlist contains a cycle of identifiers referring to each other.
|
|
|
|
|
// If this cycle contains a variable, then this variable refers to itself.
|
|
|
|
|
// Conversely, if there exists an initialization cycle involving
|
|
|
|
|
// a variable in the program, the tree walk will reach a cycle
|
|
|
|
|
// involving that variable.
|
|
|
|
|
if n.Class != PFUNC {
|
2015-09-03 17:07:00 +10:00
|
|
|
foundinitloop(n, n)
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
2015-09-03 17:07:00 +10:00
|
|
|
for i := len(initlist) - 1; i >= 0; i-- {
|
|
|
|
|
x := initlist[i]
|
|
|
|
|
if x == n {
|
|
|
|
|
break
|
|
|
|
|
}
|
|
|
|
|
if x.Class != PFUNC {
|
|
|
|
|
foundinitloop(n, x)
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// The loop involves only functions, ok.
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// reached a new unvisited node.
|
|
|
|
|
n.Initorder = InitPending
|
2015-09-03 17:07:00 +10:00
|
|
|
initlist = append(initlist, n)
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
|
// make sure that everything n depends on is initialized.
|
|
|
|
|
// n->defn is an assignment to n
|
2015-05-26 22:19:27 -04:00
|
|
|
if defn := n.Name.Defn; defn != nil {
|
|
|
|
|
switch defn.Op {
|
2015-02-13 14:40:36 -05:00
|
|
|
default:
|
2015-09-03 17:07:00 +10:00
|
|
|
Dump("defn", defn)
|
|
|
|
|
Fatalf("init1: bad defn")
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
|
case ODCLFUNC:
|
2016-03-04 16:13:17 -08:00
|
|
|
init2list(defn.Nbody, out)
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
|
case OAS:
|
2015-05-26 22:19:27 -04:00
|
|
|
if defn.Left != n {
|
2015-09-03 17:07:00 +10:00
|
|
|
Dump("defn", defn)
|
|
|
|
|
Fatalf("init1: bad defn")
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
2015-05-26 22:19:27 -04:00
|
|
|
if isblank(defn.Left) && candiscard(defn.Right) {
|
|
|
|
|
defn.Op = OEMPTY
|
|
|
|
|
defn.Left = nil
|
|
|
|
|
defn.Right = nil
|
2015-02-13 14:40:36 -05:00
|
|
|
break
|
|
|
|
|
}
|
|
|
|
|
|
2015-05-26 22:19:27 -04:00
|
|
|
init2(defn.Right, out)
|
2015-02-13 14:40:36 -05:00
|
|
|
if Debug['j'] != 0 {
|
2015-04-17 12:03:22 -04:00
|
|
|
fmt.Printf("%v\n", n.Sym)
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
2015-02-17 22:13:49 -05:00
|
|
|
if isblank(n) || !staticinit(n, out) {
|
2015-02-13 14:40:36 -05:00
|
|
|
if Debug['%'] != 0 {
|
2015-05-26 22:19:27 -04:00
|
|
|
Dump("nonstatic", defn)
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
2016-02-27 14:31:33 -08:00
|
|
|
*out = append(*out, defn)
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
2015-04-01 09:38:44 -07:00
|
|
|
case OAS2FUNC, OAS2MAPR, OAS2DOTTYPE, OAS2RECV:
|
2016-01-03 18:44:15 -08:00
|
|
|
if defn.Initorder == InitDone {
|
2015-02-13 14:40:36 -05:00
|
|
|
break
|
|
|
|
|
}
|
2016-01-03 18:44:15 -08:00
|
|
|
defn.Initorder = InitPending
|
2016-03-08 15:10:26 -08:00
|
|
|
for _, n2 := range defn.Rlist.Slice() {
|
|
|
|
|
init1(n2, out)
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
if Debug['%'] != 0 {
|
2015-05-26 22:19:27 -04:00
|
|
|
Dump("nonstatic", defn)
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
2016-02-27 14:31:33 -08:00
|
|
|
*out = append(*out, defn)
|
2016-01-03 18:44:15 -08:00
|
|
|
defn.Initorder = InitDone
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2015-09-03 17:07:00 +10:00
|
|
|
last := len(initlist) - 1
|
|
|
|
|
if initlist[last] != n {
|
|
|
|
|
Fatalf("bad initlist %v", initlist)
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
2015-09-03 17:07:00 +10:00
|
|
|
initlist[last] = nil // allow GC
|
|
|
|
|
initlist = initlist[:last]
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
|
n.Initorder = InitDone
|
|
|
|
|
return
|
2015-09-03 17:07:00 +10:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// foundinitloop prints an init loop error and exits.
|
|
|
|
|
func foundinitloop(node, visited *Node) {
|
|
|
|
|
// If there have already been errors printed,
|
|
|
|
|
// those errors probably confused us and
|
|
|
|
|
// there might not be a loop. Let the user
|
|
|
|
|
// fix those first.
|
|
|
|
|
Flusherrors()
|
|
|
|
|
if nerrors > 0 {
|
|
|
|
|
errorexit()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Find the index of node and visited in the initlist.
|
|
|
|
|
var nodeindex, visitedindex int
|
|
|
|
|
for ; initlist[nodeindex] != node; nodeindex++ {
|
|
|
|
|
}
|
|
|
|
|
for ; initlist[visitedindex] != visited; visitedindex++ {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// There is a loop involving visited. We know about node and
|
|
|
|
|
// initlist = n1 <- ... <- visited <- ... <- node <- ...
|
|
|
|
|
fmt.Printf("%v: initialization loop:\n", visited.Line())
|
|
|
|
|
|
|
|
|
|
// Print visited -> ... -> n1 -> node.
|
|
|
|
|
for _, n := range initlist[visitedindex:] {
|
|
|
|
|
fmt.Printf("\t%v %v refers to\n", n.Line(), n.Sym)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Print node -> ... -> visited.
|
|
|
|
|
for _, n := range initlist[nodeindex:visitedindex] {
|
|
|
|
|
fmt.Printf("\t%v %v refers to\n", n.Line(), n.Sym)
|
|
|
|
|
}
|
2015-02-13 14:40:36 -05:00
|
|
|
|
2015-09-03 17:07:00 +10:00
|
|
|
fmt.Printf("\t%v %v\n", visited.Line(), visited.Sym)
|
|
|
|
|
errorexit()
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// recurse over n, doing init1 everywhere.
|
2016-02-27 14:31:33 -08:00
|
|
|
func init2(n *Node, out *[]*Node) {
|
2015-02-13 14:40:36 -05:00
|
|
|
if n == nil || n.Initorder == InitDone {
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
2016-03-08 15:10:26 -08:00
|
|
|
if n.Op == ONAME && n.Ninit.Len() != 0 {
|
2016-03-15 13:06:58 -07:00
|
|
|
Fatalf("name %v with ninit: %v\n", n.Sym, Nconv(n, FmtSign))
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
init1(n, out)
|
|
|
|
|
init2(n.Left, out)
|
|
|
|
|
init2(n.Right, out)
|
|
|
|
|
init2list(n.Ninit, out)
|
|
|
|
|
init2list(n.List, out)
|
|
|
|
|
init2list(n.Rlist, out)
|
2016-03-04 16:13:17 -08:00
|
|
|
init2list(n.Nbody, out)
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
|
if n.Op == OCLOSURE {
|
2016-03-04 16:13:17 -08:00
|
|
|
init2list(n.Func.Closure.Nbody, out)
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
if n.Op == ODOTMETH || n.Op == OCALLPART {
|
2016-03-30 16:59:53 -07:00
|
|
|
init2(n.Type.Nname(), out)
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2016-03-08 10:26:20 -08:00
|
|
|
func init2list(l Nodes, out *[]*Node) {
|
2016-03-08 15:10:26 -08:00
|
|
|
for _, n := range l.Slice() {
|
|
|
|
|
init2(n, out)
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2016-03-08 10:26:20 -08:00
|
|
|
func initreorder(l []*Node, out *[]*Node) {
|
2015-02-13 14:40:36 -05:00
|
|
|
var n *Node
|
2016-03-08 15:10:26 -08:00
|
|
|
for _, n = range l {
|
2015-02-13 14:40:36 -05:00
|
|
|
switch n.Op {
|
2015-04-01 09:38:44 -07:00
|
|
|
case ODCLFUNC, ODCLCONST, ODCLTYPE:
|
2015-02-13 14:40:36 -05:00
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
|
2016-03-08 10:26:20 -08:00
|
|
|
initreorder(n.Ninit.Slice(), out)
|
2016-03-08 15:10:26 -08:00
|
|
|
n.Ninit.Set(nil)
|
2015-02-13 14:40:36 -05:00
|
|
|
init1(n, out)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// initfix computes initialization order for a list l of top-level
|
|
|
|
|
// declarations and outputs the corresponding list of statements
|
|
|
|
|
// to include in the init() function body.
|
2016-03-08 10:26:20 -08:00
|
|
|
func initfix(l []*Node) []*Node {
|
2016-02-27 14:31:33 -08:00
|
|
|
var lout []*Node
|
2015-06-03 14:16:01 -04:00
|
|
|
initplans = make(map[*Node]*InitPlan)
|
2016-03-02 17:34:42 -08:00
|
|
|
lno := lineno
|
2015-02-13 14:40:36 -05:00
|
|
|
initreorder(l, &lout)
|
2016-03-02 17:34:42 -08:00
|
|
|
lineno = lno
|
2015-06-03 14:16:01 -04:00
|
|
|
initplans = nil
|
2015-02-13 14:40:36 -05:00
|
|
|
return lout
|
|
|
|
|
}
|
|
|
|
|
|
2015-10-22 09:51:12 +09:00
|
|
|
// compilation of top-level (static) assignments
|
|
|
|
|
// into DATA statements if at all possible.
|
2016-02-27 14:31:33 -08:00
|
|
|
func staticinit(n *Node, out *[]*Node) bool {
|
2015-05-26 22:19:27 -04:00
|
|
|
if n.Op != ONAME || n.Class != PEXTERN || n.Name.Defn == nil || n.Name.Defn.Op != OAS {
|
2015-08-30 23:10:03 +02:00
|
|
|
Fatalf("staticinit")
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
lineno = n.Lineno
|
2015-05-26 22:19:27 -04:00
|
|
|
l := n.Name.Defn.Left
|
|
|
|
|
r := n.Name.Defn.Right
|
2015-02-13 14:40:36 -05:00
|
|
|
return staticassign(l, r, out)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// like staticassign but we are copying an already
|
|
|
|
|
// initialized value r.
|
2016-02-27 14:31:33 -08:00
|
|
|
func staticcopy(l *Node, r *Node, out *[]*Node) bool {
|
2015-03-04 16:33:28 -08:00
|
|
|
if r.Op != ONAME {
|
|
|
|
|
return false
|
|
|
|
|
}
|
|
|
|
|
if r.Class == PFUNC {
|
|
|
|
|
gdata(l, r, Widthptr)
|
|
|
|
|
return true
|
|
|
|
|
}
|
|
|
|
|
if r.Class != PEXTERN || r.Sym.Pkg != localpkg {
|
2015-02-17 22:13:49 -05:00
|
|
|
return false
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
2015-05-26 22:19:27 -04:00
|
|
|
if r.Name.Defn == nil { // probably zeroed but perhaps supplied externally and of unknown value
|
2015-02-17 22:13:49 -05:00
|
|
|
return false
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
2015-05-26 22:19:27 -04:00
|
|
|
if r.Name.Defn.Op != OAS {
|
2015-02-17 22:13:49 -05:00
|
|
|
return false
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
2015-02-23 16:07:24 -05:00
|
|
|
orig := r
|
2015-05-26 22:19:27 -04:00
|
|
|
r = r.Name.Defn.Right
|
2015-02-13 14:40:36 -05:00
|
|
|
|
2015-06-29 12:49:25 -04:00
|
|
|
for r.Op == OCONVNOP {
|
|
|
|
|
r = r.Left
|
|
|
|
|
}
|
|
|
|
|
|
2015-02-13 14:40:36 -05:00
|
|
|
switch r.Op {
|
|
|
|
|
case ONAME:
|
2015-02-17 22:13:49 -05:00
|
|
|
if staticcopy(l, r, out) {
|
|
|
|
|
return true
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
2016-02-27 14:31:33 -08:00
|
|
|
*out = append(*out, Nod(OAS, l, r))
|
2015-02-17 22:13:49 -05:00
|
|
|
return true
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
|
case OLITERAL:
|
2015-02-17 22:13:49 -05:00
|
|
|
if iszero(r) {
|
|
|
|
|
return true
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
gdata(l, r, int(l.Type.Width))
|
2015-02-17 22:13:49 -05:00
|
|
|
return true
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
|
case OADDR:
|
|
|
|
|
switch r.Left.Op {
|
|
|
|
|
case ONAME:
|
|
|
|
|
gdata(l, r, int(l.Type.Width))
|
2015-02-17 22:13:49 -05:00
|
|
|
return true
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
case OPTRLIT:
|
|
|
|
|
switch r.Left.Op {
|
|
|
|
|
//dump("not static addr", r);
|
|
|
|
|
default:
|
|
|
|
|
break
|
|
|
|
|
|
|
|
|
|
// copy pointer
|
2015-04-01 09:38:44 -07:00
|
|
|
case OARRAYLIT, OSTRUCTLIT, OMAPLIT:
|
2015-05-27 10:44:23 -04:00
|
|
|
gdata(l, Nod(OADDR, inittemps[r], nil), int(l.Type.Width))
|
2015-02-13 14:40:36 -05:00
|
|
|
|
2015-02-17 22:13:49 -05:00
|
|
|
return true
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
case OARRAYLIT:
|
2016-03-30 14:45:47 -07:00
|
|
|
if r.Type.IsSlice() {
|
2015-02-13 14:40:36 -05:00
|
|
|
// copy slice
|
2015-05-27 10:44:23 -04:00
|
|
|
a := inittemps[r]
|
2015-02-13 14:40:36 -05:00
|
|
|
|
2015-09-08 22:22:44 +02:00
|
|
|
n := *l
|
|
|
|
|
n.Xoffset = l.Xoffset + int64(Array_array)
|
|
|
|
|
gdata(&n, Nod(OADDR, a, nil), Widthptr)
|
|
|
|
|
n.Xoffset = l.Xoffset + int64(Array_nel)
|
|
|
|
|
gdata(&n, r.Right, Widthint)
|
|
|
|
|
n.Xoffset = l.Xoffset + int64(Array_cap)
|
|
|
|
|
gdata(&n, r.Right, Widthint)
|
2015-02-17 22:13:49 -05:00
|
|
|
return true
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
fallthrough
|
|
|
|
|
case OSTRUCTLIT:
|
2015-05-22 01:16:52 -04:00
|
|
|
p := initplans[r]
|
2015-02-13 14:40:36 -05:00
|
|
|
|
2015-09-08 22:22:44 +02:00
|
|
|
n := *l
|
|
|
|
|
for i := range p.E {
|
|
|
|
|
e := &p.E[i]
|
|
|
|
|
n.Xoffset = l.Xoffset + e.Xoffset
|
|
|
|
|
n.Type = e.Expr.Type
|
2015-02-13 14:40:36 -05:00
|
|
|
if e.Expr.Op == OLITERAL {
|
2015-09-08 22:22:44 +02:00
|
|
|
gdata(&n, e.Expr, int(n.Type.Width))
|
2015-02-13 14:40:36 -05:00
|
|
|
} else {
|
2015-09-08 22:22:44 +02:00
|
|
|
ll := Nod(OXXX, nil, nil)
|
|
|
|
|
*ll = n
|
2015-02-13 14:40:36 -05:00
|
|
|
ll.Orig = ll // completely separate copy
|
2015-02-17 22:13:49 -05:00
|
|
|
if !staticassign(ll, e.Expr, out) {
|
2015-02-13 14:40:36 -05:00
|
|
|
// Requires computation, but we're
|
|
|
|
|
// copying someone else's computation.
|
2015-09-08 22:22:44 +02:00
|
|
|
rr := Nod(OXXX, nil, nil)
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
|
*rr = *orig
|
|
|
|
|
rr.Orig = rr // completely separate copy
|
|
|
|
|
rr.Type = ll.Type
|
|
|
|
|
rr.Xoffset += e.Xoffset
|
2015-06-29 16:30:19 -04:00
|
|
|
setlineno(rr)
|
2016-02-27 14:31:33 -08:00
|
|
|
*out = append(*out, Nod(OAS, ll, rr))
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2015-02-17 22:13:49 -05:00
|
|
|
return true
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
2015-02-17 22:13:49 -05:00
|
|
|
return false
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
2016-02-27 14:31:33 -08:00
|
|
|
func staticassign(l *Node, r *Node, out *[]*Node) bool {
|
2015-06-29 12:49:25 -04:00
|
|
|
for r.Op == OCONVNOP {
|
|
|
|
|
r = r.Left
|
|
|
|
|
}
|
|
|
|
|
|
2015-02-13 14:40:36 -05:00
|
|
|
switch r.Op {
|
|
|
|
|
case ONAME:
|
2015-03-04 16:33:28 -08:00
|
|
|
return staticcopy(l, r, out)
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
|
case OLITERAL:
|
2015-02-17 22:13:49 -05:00
|
|
|
if iszero(r) {
|
|
|
|
|
return true
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
gdata(l, r, int(l.Type.Width))
|
2015-02-17 22:13:49 -05:00
|
|
|
return true
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
|
case OADDR:
|
2015-02-23 16:07:24 -05:00
|
|
|
var nam Node
|
2015-02-17 22:13:49 -05:00
|
|
|
if stataddr(&nam, r.Left) {
|
2015-09-08 22:22:44 +02:00
|
|
|
n := *r
|
|
|
|
|
n.Left = &nam
|
|
|
|
|
gdata(l, &n, int(l.Type.Width))
|
2015-02-17 22:13:49 -05:00
|
|
|
return true
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
fallthrough
|
|
|
|
|
|
|
|
|
|
case OPTRLIT:
|
|
|
|
|
switch r.Left.Op {
|
2015-04-01 09:38:44 -07:00
|
|
|
case OARRAYLIT, OMAPLIT, OSTRUCTLIT:
|
cmd/compile: captureless closures are constants
In particular, we can initialize globals with them at link time instead
of generating code for them in an init() function. Less code, less
startup cost.
But the real reason for this change is binary size. This change reduces
the binary size of hello world by ~4%.
The culprit is fmt.ssFree, a global variable which is a sync.Pool of
scratch scan states. It is initalized with a captureless closure as the
pool's New action. That action in turn references all the scanf code.
If you never call any of the fmt.Scanf* routines, ssFree is never used.
But before this change, ssFree is still referenced by fmt's init
function. That keeps ssFree and all the code it references in the
binary. With this change, ssFree is initialized at link time. As a
result, fmt.init never mentions ssFree. If you don't call fmt.Scanf*,
ssFree is unreferenced and it and the scanf code are not included.
This change is an easy fix for what is generally a much harder problem,
the unnecessary initializing of unused globals (and retention of code
that they reference). Ideally we should have separate init code for
each global and only include that code if the corresponding global is
live. (We'd need to make sure that the initializing code has no side
effects, except on the global being initialized.) That is a much harder
change.
Update #6853
Change-Id: I19d1e33992287882c83efea6ce113b7cfc504b67
Reviewed-on: https://go-review.googlesource.com/17398
Reviewed-by: Russ Cox <rsc@golang.org>
Run-TryBot: Russ Cox <rsc@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
2015-12-03 13:20:58 -08:00
|
|
|
// Init pointer.
|
2015-02-23 16:07:24 -05:00
|
|
|
a := staticname(r.Left.Type, 1)
|
2015-02-13 14:40:36 -05:00
|
|
|
|
2015-05-27 10:44:23 -04:00
|
|
|
inittemps[r] = a
|
2015-02-13 14:40:36 -05:00
|
|
|
gdata(l, Nod(OADDR, a, nil), int(l.Type.Width))
|
|
|
|
|
|
|
|
|
|
// Init underlying literal.
|
2015-02-17 22:13:49 -05:00
|
|
|
if !staticassign(a, r.Left, out) {
|
2016-02-27 14:31:33 -08:00
|
|
|
*out = append(*out, Nod(OAS, a, r.Left))
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
2015-02-17 22:13:49 -05:00
|
|
|
return true
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
cmd/compile: captureless closures are constants
In particular, we can initialize globals with them at link time instead
of generating code for them in an init() function. Less code, less
startup cost.
But the real reason for this change is binary size. This change reduces
the binary size of hello world by ~4%.
The culprit is fmt.ssFree, a global variable which is a sync.Pool of
scratch scan states. It is initalized with a captureless closure as the
pool's New action. That action in turn references all the scanf code.
If you never call any of the fmt.Scanf* routines, ssFree is never used.
But before this change, ssFree is still referenced by fmt's init
function. That keeps ssFree and all the code it references in the
binary. With this change, ssFree is initialized at link time. As a
result, fmt.init never mentions ssFree. If you don't call fmt.Scanf*,
ssFree is unreferenced and it and the scanf code are not included.
This change is an easy fix for what is generally a much harder problem,
the unnecessary initializing of unused globals (and retention of code
that they reference). Ideally we should have separate init code for
each global and only include that code if the corresponding global is
live. (We'd need to make sure that the initializing code has no side
effects, except on the global being initialized.) That is a much harder
change.
Update #6853
Change-Id: I19d1e33992287882c83efea6ce113b7cfc504b67
Reviewed-on: https://go-review.googlesource.com/17398
Reviewed-by: Russ Cox <rsc@golang.org>
Run-TryBot: Russ Cox <rsc@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
2015-12-03 13:20:58 -08:00
|
|
|
//dump("not static ptrlit", r);
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
|
case OSTRARRAYBYTE:
|
|
|
|
|
if l.Class == PEXTERN && r.Left.Op == OLITERAL {
|
2015-05-27 00:47:05 -04:00
|
|
|
sval := r.Left.Val().U.(string)
|
2015-03-02 16:03:26 -05:00
|
|
|
slicebytes(l, sval, len(sval))
|
2015-02-17 22:13:49 -05:00
|
|
|
return true
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
case OARRAYLIT:
|
|
|
|
|
initplan(r)
|
2016-03-30 14:45:47 -07:00
|
|
|
if r.Type.IsSlice() {
|
2015-02-13 14:40:36 -05:00
|
|
|
// Init slice.
|
2016-04-01 14:51:02 -07:00
|
|
|
bound := r.Right.Int64()
|
2016-03-30 10:57:47 -07:00
|
|
|
ta := typArray(r.Type.Elem(), bound)
|
2015-02-23 16:07:24 -05:00
|
|
|
a := staticname(ta, 1)
|
2015-05-27 10:44:23 -04:00
|
|
|
inittemps[r] = a
|
2015-09-08 22:22:44 +02:00
|
|
|
n := *l
|
|
|
|
|
n.Xoffset = l.Xoffset + int64(Array_array)
|
|
|
|
|
gdata(&n, Nod(OADDR, a, nil), Widthptr)
|
|
|
|
|
n.Xoffset = l.Xoffset + int64(Array_nel)
|
|
|
|
|
gdata(&n, r.Right, Widthint)
|
|
|
|
|
n.Xoffset = l.Xoffset + int64(Array_cap)
|
|
|
|
|
gdata(&n, r.Right, Widthint)
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
|
// Fall through to init underlying array.
|
|
|
|
|
l = a
|
|
|
|
|
}
|
|
|
|
|
fallthrough
|
|
|
|
|
|
|
|
|
|
case OSTRUCTLIT:
|
|
|
|
|
initplan(r)
|
|
|
|
|
|
2015-05-22 01:16:52 -04:00
|
|
|
p := initplans[r]
|
2015-09-08 22:22:44 +02:00
|
|
|
n := *l
|
|
|
|
|
for i := range p.E {
|
|
|
|
|
e := &p.E[i]
|
|
|
|
|
n.Xoffset = l.Xoffset + e.Xoffset
|
|
|
|
|
n.Type = e.Expr.Type
|
2015-02-13 14:40:36 -05:00
|
|
|
if e.Expr.Op == OLITERAL {
|
2015-09-08 22:22:44 +02:00
|
|
|
gdata(&n, e.Expr, int(n.Type.Width))
|
2015-02-13 14:40:36 -05:00
|
|
|
} else {
|
2015-06-29 16:30:19 -04:00
|
|
|
setlineno(e.Expr)
|
2015-09-08 22:22:44 +02:00
|
|
|
a := Nod(OXXX, nil, nil)
|
|
|
|
|
*a = n
|
2015-02-13 14:40:36 -05:00
|
|
|
a.Orig = a // completely separate copy
|
2015-02-17 22:13:49 -05:00
|
|
|
if !staticassign(a, e.Expr, out) {
|
2016-02-27 14:31:33 -08:00
|
|
|
*out = append(*out, Nod(OAS, a, e.Expr))
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2015-02-17 22:13:49 -05:00
|
|
|
return true
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
|
case OMAPLIT:
|
|
|
|
|
break
|
cmd/compile: captureless closures are constants
In particular, we can initialize globals with them at link time instead
of generating code for them in an init() function. Less code, less
startup cost.
But the real reason for this change is binary size. This change reduces
the binary size of hello world by ~4%.
The culprit is fmt.ssFree, a global variable which is a sync.Pool of
scratch scan states. It is initalized with a captureless closure as the
pool's New action. That action in turn references all the scanf code.
If you never call any of the fmt.Scanf* routines, ssFree is never used.
But before this change, ssFree is still referenced by fmt's init
function. That keeps ssFree and all the code it references in the
binary. With this change, ssFree is initialized at link time. As a
result, fmt.init never mentions ssFree. If you don't call fmt.Scanf*,
ssFree is unreferenced and it and the scanf code are not included.
This change is an easy fix for what is generally a much harder problem,
the unnecessary initializing of unused globals (and retention of code
that they reference). Ideally we should have separate init code for
each global and only include that code if the corresponding global is
live. (We'd need to make sure that the initializing code has no side
effects, except on the global being initialized.) That is a much harder
change.
Update #6853
Change-Id: I19d1e33992287882c83efea6ce113b7cfc504b67
Reviewed-on: https://go-review.googlesource.com/17398
Reviewed-by: Russ Cox <rsc@golang.org>
Run-TryBot: Russ Cox <rsc@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
2015-12-03 13:20:58 -08:00
|
|
|
|
|
|
|
|
case OCLOSURE:
|
cmd/compile: ignore OXXX nodes in closure captured vars list
Added a debug flag "-d closure" to explain compilation of
closures (should this be done some other way? Should we
rewrite the "-m" flag to "-d escapes"?) Used this to
discover that cause was an OXXX node in the captured vars
list, and in turn noticed that OXXX nodes are explicitly
ignored in all other processing of captured variables.
Couldn't figure out a reproducer, did verify that this OXXX
was not caused by an unnamed return value (which is one use
of these). Verified lack of heap allocation by examining -S
output.
Assembly:
(runtime/mgc.go:1371) PCDATA $0, $2
(runtime/mgc.go:1371) CALL "".notewakeup(SB)
(runtime/mgc.go:1377) LEAQ "".gcBgMarkWorker.func1·f(SB), AX
(runtime/mgc.go:1404) MOVQ AX, (SP)
(runtime/mgc.go:1404) MOVQ "".autotmp_2242+88(SP), CX
(runtime/mgc.go:1404) MOVQ CX, 8(SP)
(runtime/mgc.go:1404) LEAQ go.string."GC worker (idle)"(SB), AX
(runtime/mgc.go:1404) MOVQ AX, 16(SP)
(runtime/mgc.go:1404) MOVQ $16, 24(SP)
(runtime/mgc.go:1404) MOVB $20, 32(SP)
(runtime/mgc.go:1404) MOVQ $0, 40(SP)
(runtime/mgc.go:1404) PCDATA $0, $2
(runtime/mgc.go:1404) CALL "".gopark(SB)
Added a check for compiling_runtime to ensure that this is
caught in the future. Added a test to test the check.
Verified that 1.5.3 did NOT reject the test case when
compiled with -+ flag, so this is not a recently added bug.
Cause of bug is two-part -- there was no leaking closure
detection ever, and instead it relied on capture-of-variables
to trigger compiling_runtime test, but closures improved in
1.5.3 so that mere capture of a value did not also capture
the variable, which thus allowed closures to escape, as well
as this case where the escape was spurious. In
fixedbugs/issue14999.go, compare messages for f and g;
1.5.3 would reject g, but not f. 1.4 rejects both because
1.4 heap-allocates parameter x for both.
Fixes #14999.
Change-Id: I40bcdd27056810628e96763a44f2acddd503aee1
Reviewed-on: https://go-review.googlesource.com/21322
Run-TryBot: David Chase <drchase@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Keith Randall <khr@golang.org>
2016-03-30 14:14:00 -04:00
|
|
|
if hasemptycvars(r) {
|
|
|
|
|
if Debug_closure > 0 {
|
|
|
|
|
Warnl(r.Lineno, "closure converted to global")
|
|
|
|
|
}
|
cmd/compile: captureless closures are constants
In particular, we can initialize globals with them at link time instead
of generating code for them in an init() function. Less code, less
startup cost.
But the real reason for this change is binary size. This change reduces
the binary size of hello world by ~4%.
The culprit is fmt.ssFree, a global variable which is a sync.Pool of
scratch scan states. It is initalized with a captureless closure as the
pool's New action. That action in turn references all the scanf code.
If you never call any of the fmt.Scanf* routines, ssFree is never used.
But before this change, ssFree is still referenced by fmt's init
function. That keeps ssFree and all the code it references in the
binary. With this change, ssFree is initialized at link time. As a
result, fmt.init never mentions ssFree. If you don't call fmt.Scanf*,
ssFree is unreferenced and it and the scanf code are not included.
This change is an easy fix for what is generally a much harder problem,
the unnecessary initializing of unused globals (and retention of code
that they reference). Ideally we should have separate init code for
each global and only include that code if the corresponding global is
live. (We'd need to make sure that the initializing code has no side
effects, except on the global being initialized.) That is a much harder
change.
Update #6853
Change-Id: I19d1e33992287882c83efea6ce113b7cfc504b67
Reviewed-on: https://go-review.googlesource.com/17398
Reviewed-by: Russ Cox <rsc@golang.org>
Run-TryBot: Russ Cox <rsc@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
2015-12-03 13:20:58 -08:00
|
|
|
// Closures with no captured variables are globals,
|
|
|
|
|
// so the assignment can be done at link time.
|
|
|
|
|
n := *l
|
|
|
|
|
gdata(&n, r.Func.Closure.Func.Nname, Widthptr)
|
|
|
|
|
return true
|
cmd/compile: ignore OXXX nodes in closure captured vars list
Added a debug flag "-d closure" to explain compilation of
closures (should this be done some other way? Should we
rewrite the "-m" flag to "-d escapes"?) Used this to
discover that cause was an OXXX node in the captured vars
list, and in turn noticed that OXXX nodes are explicitly
ignored in all other processing of captured variables.
Couldn't figure out a reproducer, did verify that this OXXX
was not caused by an unnamed return value (which is one use
of these). Verified lack of heap allocation by examining -S
output.
Assembly:
(runtime/mgc.go:1371) PCDATA $0, $2
(runtime/mgc.go:1371) CALL "".notewakeup(SB)
(runtime/mgc.go:1377) LEAQ "".gcBgMarkWorker.func1·f(SB), AX
(runtime/mgc.go:1404) MOVQ AX, (SP)
(runtime/mgc.go:1404) MOVQ "".autotmp_2242+88(SP), CX
(runtime/mgc.go:1404) MOVQ CX, 8(SP)
(runtime/mgc.go:1404) LEAQ go.string."GC worker (idle)"(SB), AX
(runtime/mgc.go:1404) MOVQ AX, 16(SP)
(runtime/mgc.go:1404) MOVQ $16, 24(SP)
(runtime/mgc.go:1404) MOVB $20, 32(SP)
(runtime/mgc.go:1404) MOVQ $0, 40(SP)
(runtime/mgc.go:1404) PCDATA $0, $2
(runtime/mgc.go:1404) CALL "".gopark(SB)
Added a check for compiling_runtime to ensure that this is
caught in the future. Added a test to test the check.
Verified that 1.5.3 did NOT reject the test case when
compiled with -+ flag, so this is not a recently added bug.
Cause of bug is two-part -- there was no leaking closure
detection ever, and instead it relied on capture-of-variables
to trigger compiling_runtime test, but closures improved in
1.5.3 so that mere capture of a value did not also capture
the variable, which thus allowed closures to escape, as well
as this case where the escape was spurious. In
fixedbugs/issue14999.go, compare messages for f and g;
1.5.3 would reject g, but not f. 1.4 rejects both because
1.4 heap-allocates parameter x for both.
Fixes #14999.
Change-Id: I40bcdd27056810628e96763a44f2acddd503aee1
Reviewed-on: https://go-review.googlesource.com/21322
Run-TryBot: David Chase <drchase@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Keith Randall <khr@golang.org>
2016-03-30 14:14:00 -04:00
|
|
|
} else {
|
|
|
|
|
closuredebugruntimecheck(r)
|
cmd/compile: captureless closures are constants
In particular, we can initialize globals with them at link time instead
of generating code for them in an init() function. Less code, less
startup cost.
But the real reason for this change is binary size. This change reduces
the binary size of hello world by ~4%.
The culprit is fmt.ssFree, a global variable which is a sync.Pool of
scratch scan states. It is initalized with a captureless closure as the
pool's New action. That action in turn references all the scanf code.
If you never call any of the fmt.Scanf* routines, ssFree is never used.
But before this change, ssFree is still referenced by fmt's init
function. That keeps ssFree and all the code it references in the
binary. With this change, ssFree is initialized at link time. As a
result, fmt.init never mentions ssFree. If you don't call fmt.Scanf*,
ssFree is unreferenced and it and the scanf code are not included.
This change is an easy fix for what is generally a much harder problem,
the unnecessary initializing of unused globals (and retention of code
that they reference). Ideally we should have separate init code for
each global and only include that code if the corresponding global is
live. (We'd need to make sure that the initializing code has no side
effects, except on the global being initialized.) That is a much harder
change.
Update #6853
Change-Id: I19d1e33992287882c83efea6ce113b7cfc504b67
Reviewed-on: https://go-review.googlesource.com/17398
Reviewed-by: Russ Cox <rsc@golang.org>
Run-TryBot: Russ Cox <rsc@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
2015-12-03 13:20:58 -08:00
|
|
|
}
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
cmd/compile: captureless closures are constants
In particular, we can initialize globals with them at link time instead
of generating code for them in an init() function. Less code, less
startup cost.
But the real reason for this change is binary size. This change reduces
the binary size of hello world by ~4%.
The culprit is fmt.ssFree, a global variable which is a sync.Pool of
scratch scan states. It is initalized with a captureless closure as the
pool's New action. That action in turn references all the scanf code.
If you never call any of the fmt.Scanf* routines, ssFree is never used.
But before this change, ssFree is still referenced by fmt's init
function. That keeps ssFree and all the code it references in the
binary. With this change, ssFree is initialized at link time. As a
result, fmt.init never mentions ssFree. If you don't call fmt.Scanf*,
ssFree is unreferenced and it and the scanf code are not included.
This change is an easy fix for what is generally a much harder problem,
the unnecessary initializing of unused globals (and retention of code
that they reference). Ideally we should have separate init code for
each global and only include that code if the corresponding global is
live. (We'd need to make sure that the initializing code has no side
effects, except on the global being initialized.) That is a much harder
change.
Update #6853
Change-Id: I19d1e33992287882c83efea6ce113b7cfc504b67
Reviewed-on: https://go-review.googlesource.com/17398
Reviewed-by: Russ Cox <rsc@golang.org>
Run-TryBot: Russ Cox <rsc@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
2015-12-03 13:20:58 -08:00
|
|
|
//dump("not static", r);
|
2015-02-17 22:13:49 -05:00
|
|
|
return false
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
2015-10-22 09:51:12 +09:00
|
|
|
// from here down is the walk analysis
|
|
|
|
|
// of composite literals.
|
|
|
|
|
// most of the work is to generate
|
|
|
|
|
// data statements for the constant
|
|
|
|
|
// part of the composite literal.
|
2015-02-13 14:40:36 -05:00
|
|
|
func staticname(t *Type, ctxt int) *Node {
|
2016-03-19 18:17:58 -07:00
|
|
|
n := newname(LookupN("statictmp_", statuniqgen))
|
2015-02-13 14:40:36 -05:00
|
|
|
statuniqgen++
|
2015-02-17 22:13:49 -05:00
|
|
|
if ctxt == 0 {
|
2015-05-15 10:02:19 -07:00
|
|
|
n.Name.Readonly = true
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
addvar(n, t, PEXTERN)
|
|
|
|
|
return n
|
|
|
|
|
}
|
|
|
|
|
|
2015-02-17 22:13:49 -05:00
|
|
|
func isliteral(n *Node) bool {
|
2016-03-13 21:51:07 -07:00
|
|
|
// Treat nils as zeros rather than literals.
|
2016-03-13 21:57:31 -07:00
|
|
|
return n.Op == OLITERAL && n.Val().Ctype() != CTNIL
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
2016-03-14 14:03:57 -07:00
|
|
|
func (n *Node) isSimpleName() bool {
|
2016-05-25 10:29:50 -04:00
|
|
|
return n.Op == ONAME && n.Addable && n.Class != PAUTOHEAP
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
2016-03-07 22:54:46 -08:00
|
|
|
func litas(l *Node, r *Node, init *Nodes) {
|
2015-02-23 16:07:24 -05:00
|
|
|
a := Nod(OAS, l, r)
|
cmd/compile: reduce use of **Node parameters
Escape analysis has a hard time with tree-like
structures (see #13493 and #14858).
This is unlikely to change.
As a result, when invoking a function that accepts
a **Node parameter, we usually allocate a *Node
on the heap. This happens a whole lot.
This CL changes functions from taking a **Node
to acting more like append: It both modifies
the input and returns a replacement for it.
Because of the cascading nature of escape analysis,
in order to get the benefits, I had to modify
almost all such functions. The remaining functions
are in racewalk and the backend. I would be happy
to update them as well in a separate CL.
This CL was created by manually updating the
function signatures and the directly impacted
bits of code. The callsites were then automatically
updated using a bespoke script:
https://gist.github.com/josharian/046b1be7aceae244de39
For ease of reviewing and future understanding,
this CL is also broken down into four CLs,
mailed separately, which show the manual
and the automated changes separately.
They are CLs 20990, 20991, 20992, and 20993.
Passes toolstash -cmp.
name old time/op new time/op delta
Template 335ms ± 5% 324ms ± 5% -3.35% (p=0.000 n=23+24)
Unicode 176ms ± 9% 165ms ± 6% -6.12% (p=0.000 n=23+24)
GoTypes 1.10s ± 4% 1.07s ± 2% -2.77% (p=0.000 n=24+24)
Compiler 5.31s ± 3% 5.15s ± 3% -2.95% (p=0.000 n=24+24)
MakeBash 41.6s ± 1% 41.7s ± 2% ~ (p=0.586 n=23+23)
name old alloc/op new alloc/op delta
Template 63.3MB ± 0% 62.4MB ± 0% -1.36% (p=0.000 n=25+23)
Unicode 42.4MB ± 0% 41.6MB ± 0% -1.99% (p=0.000 n=24+25)
GoTypes 220MB ± 0% 217MB ± 0% -1.11% (p=0.000 n=25+25)
Compiler 994MB ± 0% 973MB ± 0% -2.08% (p=0.000 n=24+25)
name old allocs/op new allocs/op delta
Template 681k ± 0% 574k ± 0% -15.71% (p=0.000 n=24+25)
Unicode 518k ± 0% 413k ± 0% -20.34% (p=0.000 n=25+24)
GoTypes 2.08M ± 0% 1.78M ± 0% -14.62% (p=0.000 n=25+25)
Compiler 9.26M ± 0% 7.64M ± 0% -17.48% (p=0.000 n=25+25)
name old text-bytes new text-bytes delta
HelloSize 578k ± 0% 578k ± 0% ~ (all samples are equal)
CmdGoSize 6.46M ± 0% 6.46M ± 0% ~ (all samples are equal)
name old data-bytes new data-bytes delta
HelloSize 128k ± 0% 128k ± 0% ~ (all samples are equal)
CmdGoSize 281k ± 0% 281k ± 0% ~ (all samples are equal)
name old exe-bytes new exe-bytes delta
HelloSize 921k ± 0% 921k ± 0% ~ (all samples are equal)
CmdGoSize 9.86M ± 0% 9.86M ± 0% ~ (all samples are equal)
Change-Id: I277d95bd56d51c166ef7f560647aeaa092f3f475
Reviewed-on: https://go-review.googlesource.com/20959
Reviewed-by: Dave Cheney <dave@cheney.net>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
2016-03-20 08:03:31 -07:00
|
|
|
a = typecheck(a, Etop)
|
|
|
|
|
a = walkexpr(a, init)
|
2016-03-07 22:54:46 -08:00
|
|
|
init.Append(a)
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
2016-03-13 17:06:10 -07:00
|
|
|
// initGenType is a bitmap indicating the types of generation that will occur for a static value.
|
|
|
|
|
type initGenType uint8
|
|
|
|
|
|
2015-02-13 14:40:36 -05:00
|
|
|
const (
|
2016-03-13 17:06:10 -07:00
|
|
|
initDynamic initGenType = 1 << iota // contains some dynamic values, for which init code will be generated
|
|
|
|
|
initConst // contains some constant values, which may be written into data symbols
|
2015-02-13 14:40:36 -05:00
|
|
|
)
|
|
|
|
|
|
2016-05-16 14:28:44 -07:00
|
|
|
// getdyn calculates the initGenType for n.
|
|
|
|
|
// If top is false, getdyn is recursing.
|
|
|
|
|
func getdyn(n *Node, top bool) initGenType {
|
2015-02-13 14:40:36 -05:00
|
|
|
switch n.Op {
|
|
|
|
|
default:
|
2015-02-17 22:13:49 -05:00
|
|
|
if isliteral(n) {
|
2016-03-13 17:06:10 -07:00
|
|
|
return initConst
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
2016-03-13 17:06:10 -07:00
|
|
|
return initDynamic
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
|
case OARRAYLIT:
|
2016-05-16 14:28:44 -07:00
|
|
|
if !top && n.Type.IsSlice() {
|
2016-03-13 17:06:10 -07:00
|
|
|
return initDynamic
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
case OSTRUCTLIT:
|
|
|
|
|
}
|
2016-03-13 17:06:10 -07:00
|
|
|
|
|
|
|
|
var mode initGenType
|
2016-03-08 15:10:26 -08:00
|
|
|
for _, n1 := range n.List.Slice() {
|
|
|
|
|
value := n1.Right
|
2016-05-16 14:28:44 -07:00
|
|
|
mode |= getdyn(value, false)
|
2016-03-13 17:06:10 -07:00
|
|
|
if mode == initDynamic|initConst {
|
2015-02-13 14:40:36 -05:00
|
|
|
break
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return mode
|
|
|
|
|
}
|
|
|
|
|
|
2016-04-18 11:17:55 -07:00
|
|
|
// isStaticCompositeLiteral reports whether n is a compile-time constant.
|
|
|
|
|
func isStaticCompositeLiteral(n *Node) bool {
|
2016-04-19 12:08:33 -07:00
|
|
|
switch n.Op {
|
|
|
|
|
case OARRAYLIT:
|
|
|
|
|
if n.Type.IsSlice() {
|
|
|
|
|
return false
|
|
|
|
|
}
|
|
|
|
|
case OSTRUCTLIT:
|
|
|
|
|
case OLITERAL:
|
|
|
|
|
return true
|
|
|
|
|
default:
|
|
|
|
|
return false
|
|
|
|
|
}
|
2016-04-18 11:17:55 -07:00
|
|
|
for _, r := range n.List.Slice() {
|
|
|
|
|
if r.Op != OKEY {
|
|
|
|
|
Fatalf("isStaticCompositeLiteral: rhs not OKEY: %v", r)
|
|
|
|
|
}
|
|
|
|
|
index := r.Left
|
|
|
|
|
if n.Op == OARRAYLIT && index.Op != OLITERAL {
|
|
|
|
|
return false
|
|
|
|
|
}
|
|
|
|
|
value := r.Right
|
2016-04-19 12:08:33 -07:00
|
|
|
if !isStaticCompositeLiteral(value) {
|
|
|
|
|
return false
|
2016-04-18 11:17:55 -07:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return true
|
|
|
|
|
}
|
|
|
|
|
|
2016-03-07 22:54:46 -08:00
|
|
|
func structlit(ctxt int, pass int, n *Node, var_ *Node, init *Nodes) {
|
2016-03-08 15:10:26 -08:00
|
|
|
for _, r := range n.List.Slice() {
|
2015-02-13 14:40:36 -05:00
|
|
|
if r.Op != OKEY {
|
2015-08-30 23:10:03 +02:00
|
|
|
Fatalf("structlit: rhs not OKEY: %v", r)
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
2015-09-08 22:22:44 +02:00
|
|
|
index := r.Left
|
|
|
|
|
value := r.Right
|
|
|
|
|
|
2015-02-13 14:40:36 -05:00
|
|
|
switch value.Op {
|
|
|
|
|
case OARRAYLIT:
|
2016-03-29 09:14:19 -07:00
|
|
|
if value.Type.IsSlice() {
|
2015-02-13 14:40:36 -05:00
|
|
|
if pass == 1 && ctxt != 0 {
|
2016-03-24 20:57:53 +11:00
|
|
|
a := NodSym(ODOT, var_, index.Sym)
|
2015-02-13 14:40:36 -05:00
|
|
|
slicelit(ctxt, value, a, init)
|
|
|
|
|
} else if pass == 2 && ctxt == 0 {
|
2016-03-24 20:57:53 +11:00
|
|
|
a := NodSym(ODOT, var_, index.Sym)
|
2015-02-13 14:40:36 -05:00
|
|
|
slicelit(ctxt, value, a, init)
|
|
|
|
|
} else if pass == 3 {
|
|
|
|
|
break
|
|
|
|
|
}
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
|
2016-03-24 20:57:53 +11:00
|
|
|
a := NodSym(ODOT, var_, index.Sym)
|
2015-02-13 14:40:36 -05:00
|
|
|
arraylit(ctxt, pass, value, a, init)
|
|
|
|
|
continue
|
|
|
|
|
|
|
|
|
|
case OSTRUCTLIT:
|
2016-03-24 20:57:53 +11:00
|
|
|
a := NodSym(ODOT, var_, index.Sym)
|
2015-02-13 14:40:36 -05:00
|
|
|
structlit(ctxt, pass, value, a, init)
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
|
2015-02-17 22:13:49 -05:00
|
|
|
if isliteral(value) {
|
2015-02-13 14:40:36 -05:00
|
|
|
if pass == 2 {
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
} else if pass == 1 {
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// build list of var.field = expr
|
2015-06-29 16:30:19 -04:00
|
|
|
setlineno(value)
|
2016-03-24 20:57:53 +11:00
|
|
|
a := NodSym(ODOT, var_, index.Sym)
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
|
a = Nod(OAS, a, value)
|
cmd/compile: reduce use of **Node parameters
Escape analysis has a hard time with tree-like
structures (see #13493 and #14858).
This is unlikely to change.
As a result, when invoking a function that accepts
a **Node parameter, we usually allocate a *Node
on the heap. This happens a whole lot.
This CL changes functions from taking a **Node
to acting more like append: It both modifies
the input and returns a replacement for it.
Because of the cascading nature of escape analysis,
in order to get the benefits, I had to modify
almost all such functions. The remaining functions
are in racewalk and the backend. I would be happy
to update them as well in a separate CL.
This CL was created by manually updating the
function signatures and the directly impacted
bits of code. The callsites were then automatically
updated using a bespoke script:
https://gist.github.com/josharian/046b1be7aceae244de39
For ease of reviewing and future understanding,
this CL is also broken down into four CLs,
mailed separately, which show the manual
and the automated changes separately.
They are CLs 20990, 20991, 20992, and 20993.
Passes toolstash -cmp.
name old time/op new time/op delta
Template 335ms ± 5% 324ms ± 5% -3.35% (p=0.000 n=23+24)
Unicode 176ms ± 9% 165ms ± 6% -6.12% (p=0.000 n=23+24)
GoTypes 1.10s ± 4% 1.07s ± 2% -2.77% (p=0.000 n=24+24)
Compiler 5.31s ± 3% 5.15s ± 3% -2.95% (p=0.000 n=24+24)
MakeBash 41.6s ± 1% 41.7s ± 2% ~ (p=0.586 n=23+23)
name old alloc/op new alloc/op delta
Template 63.3MB ± 0% 62.4MB ± 0% -1.36% (p=0.000 n=25+23)
Unicode 42.4MB ± 0% 41.6MB ± 0% -1.99% (p=0.000 n=24+25)
GoTypes 220MB ± 0% 217MB ± 0% -1.11% (p=0.000 n=25+25)
Compiler 994MB ± 0% 973MB ± 0% -2.08% (p=0.000 n=24+25)
name old allocs/op new allocs/op delta
Template 681k ± 0% 574k ± 0% -15.71% (p=0.000 n=24+25)
Unicode 518k ± 0% 413k ± 0% -20.34% (p=0.000 n=25+24)
GoTypes 2.08M ± 0% 1.78M ± 0% -14.62% (p=0.000 n=25+25)
Compiler 9.26M ± 0% 7.64M ± 0% -17.48% (p=0.000 n=25+25)
name old text-bytes new text-bytes delta
HelloSize 578k ± 0% 578k ± 0% ~ (all samples are equal)
CmdGoSize 6.46M ± 0% 6.46M ± 0% ~ (all samples are equal)
name old data-bytes new data-bytes delta
HelloSize 128k ± 0% 128k ± 0% ~ (all samples are equal)
CmdGoSize 281k ± 0% 281k ± 0% ~ (all samples are equal)
name old exe-bytes new exe-bytes delta
HelloSize 921k ± 0% 921k ± 0% ~ (all samples are equal)
CmdGoSize 9.86M ± 0% 9.86M ± 0% ~ (all samples are equal)
Change-Id: I277d95bd56d51c166ef7f560647aeaa092f3f475
Reviewed-on: https://go-review.googlesource.com/20959
Reviewed-by: Dave Cheney <dave@cheney.net>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
2016-03-20 08:03:31 -07:00
|
|
|
a = typecheck(a, Etop)
|
2015-02-13 14:40:36 -05:00
|
|
|
if pass == 1 {
|
cmd/compile: reduce use of **Node parameters
Escape analysis has a hard time with tree-like
structures (see #13493 and #14858).
This is unlikely to change.
As a result, when invoking a function that accepts
a **Node parameter, we usually allocate a *Node
on the heap. This happens a whole lot.
This CL changes functions from taking a **Node
to acting more like append: It both modifies
the input and returns a replacement for it.
Because of the cascading nature of escape analysis,
in order to get the benefits, I had to modify
almost all such functions. The remaining functions
are in racewalk and the backend. I would be happy
to update them as well in a separate CL.
This CL was created by manually updating the
function signatures and the directly impacted
bits of code. The callsites were then automatically
updated using a bespoke script:
https://gist.github.com/josharian/046b1be7aceae244de39
For ease of reviewing and future understanding,
this CL is also broken down into four CLs,
mailed separately, which show the manual
and the automated changes separately.
They are CLs 20990, 20991, 20992, and 20993.
Passes toolstash -cmp.
name old time/op new time/op delta
Template 335ms ± 5% 324ms ± 5% -3.35% (p=0.000 n=23+24)
Unicode 176ms ± 9% 165ms ± 6% -6.12% (p=0.000 n=23+24)
GoTypes 1.10s ± 4% 1.07s ± 2% -2.77% (p=0.000 n=24+24)
Compiler 5.31s ± 3% 5.15s ± 3% -2.95% (p=0.000 n=24+24)
MakeBash 41.6s ± 1% 41.7s ± 2% ~ (p=0.586 n=23+23)
name old alloc/op new alloc/op delta
Template 63.3MB ± 0% 62.4MB ± 0% -1.36% (p=0.000 n=25+23)
Unicode 42.4MB ± 0% 41.6MB ± 0% -1.99% (p=0.000 n=24+25)
GoTypes 220MB ± 0% 217MB ± 0% -1.11% (p=0.000 n=25+25)
Compiler 994MB ± 0% 973MB ± 0% -2.08% (p=0.000 n=24+25)
name old allocs/op new allocs/op delta
Template 681k ± 0% 574k ± 0% -15.71% (p=0.000 n=24+25)
Unicode 518k ± 0% 413k ± 0% -20.34% (p=0.000 n=25+24)
GoTypes 2.08M ± 0% 1.78M ± 0% -14.62% (p=0.000 n=25+25)
Compiler 9.26M ± 0% 7.64M ± 0% -17.48% (p=0.000 n=25+25)
name old text-bytes new text-bytes delta
HelloSize 578k ± 0% 578k ± 0% ~ (all samples are equal)
CmdGoSize 6.46M ± 0% 6.46M ± 0% ~ (all samples are equal)
name old data-bytes new data-bytes delta
HelloSize 128k ± 0% 128k ± 0% ~ (all samples are equal)
CmdGoSize 281k ± 0% 281k ± 0% ~ (all samples are equal)
name old exe-bytes new exe-bytes delta
HelloSize 921k ± 0% 921k ± 0% ~ (all samples are equal)
CmdGoSize 9.86M ± 0% 9.86M ± 0% ~ (all samples are equal)
Change-Id: I277d95bd56d51c166ef7f560647aeaa092f3f475
Reviewed-on: https://go-review.googlesource.com/20959
Reviewed-by: Dave Cheney <dave@cheney.net>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
2016-03-20 08:03:31 -07:00
|
|
|
a = walkexpr(a, init) // add any assignments in r to top
|
2015-02-13 14:40:36 -05:00
|
|
|
if a.Op != OAS {
|
2015-08-30 23:10:03 +02:00
|
|
|
Fatalf("structlit: not as")
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
2016-05-16 14:23:12 -07:00
|
|
|
a.IsStatic = true
|
2015-02-13 14:40:36 -05:00
|
|
|
} else {
|
cmd/compile: reduce use of **Node parameters
Escape analysis has a hard time with tree-like
structures (see #13493 and #14858).
This is unlikely to change.
As a result, when invoking a function that accepts
a **Node parameter, we usually allocate a *Node
on the heap. This happens a whole lot.
This CL changes functions from taking a **Node
to acting more like append: It both modifies
the input and returns a replacement for it.
Because of the cascading nature of escape analysis,
in order to get the benefits, I had to modify
almost all such functions. The remaining functions
are in racewalk and the backend. I would be happy
to update them as well in a separate CL.
This CL was created by manually updating the
function signatures and the directly impacted
bits of code. The callsites were then automatically
updated using a bespoke script:
https://gist.github.com/josharian/046b1be7aceae244de39
For ease of reviewing and future understanding,
this CL is also broken down into four CLs,
mailed separately, which show the manual
and the automated changes separately.
They are CLs 20990, 20991, 20992, and 20993.
Passes toolstash -cmp.
name old time/op new time/op delta
Template 335ms ± 5% 324ms ± 5% -3.35% (p=0.000 n=23+24)
Unicode 176ms ± 9% 165ms ± 6% -6.12% (p=0.000 n=23+24)
GoTypes 1.10s ± 4% 1.07s ± 2% -2.77% (p=0.000 n=24+24)
Compiler 5.31s ± 3% 5.15s ± 3% -2.95% (p=0.000 n=24+24)
MakeBash 41.6s ± 1% 41.7s ± 2% ~ (p=0.586 n=23+23)
name old alloc/op new alloc/op delta
Template 63.3MB ± 0% 62.4MB ± 0% -1.36% (p=0.000 n=25+23)
Unicode 42.4MB ± 0% 41.6MB ± 0% -1.99% (p=0.000 n=24+25)
GoTypes 220MB ± 0% 217MB ± 0% -1.11% (p=0.000 n=25+25)
Compiler 994MB ± 0% 973MB ± 0% -2.08% (p=0.000 n=24+25)
name old allocs/op new allocs/op delta
Template 681k ± 0% 574k ± 0% -15.71% (p=0.000 n=24+25)
Unicode 518k ± 0% 413k ± 0% -20.34% (p=0.000 n=25+24)
GoTypes 2.08M ± 0% 1.78M ± 0% -14.62% (p=0.000 n=25+25)
Compiler 9.26M ± 0% 7.64M ± 0% -17.48% (p=0.000 n=25+25)
name old text-bytes new text-bytes delta
HelloSize 578k ± 0% 578k ± 0% ~ (all samples are equal)
CmdGoSize 6.46M ± 0% 6.46M ± 0% ~ (all samples are equal)
name old data-bytes new data-bytes delta
HelloSize 128k ± 0% 128k ± 0% ~ (all samples are equal)
CmdGoSize 281k ± 0% 281k ± 0% ~ (all samples are equal)
name old exe-bytes new exe-bytes delta
HelloSize 921k ± 0% 921k ± 0% ~ (all samples are equal)
CmdGoSize 9.86M ± 0% 9.86M ± 0% ~ (all samples are equal)
Change-Id: I277d95bd56d51c166ef7f560647aeaa092f3f475
Reviewed-on: https://go-review.googlesource.com/20959
Reviewed-by: Dave Cheney <dave@cheney.net>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
2016-03-20 08:03:31 -07:00
|
|
|
a = orderstmtinplace(a)
|
|
|
|
|
a = walkstmt(a)
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
2016-03-07 22:54:46 -08:00
|
|
|
init.Append(a)
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2016-03-07 22:54:46 -08:00
|
|
|
func arraylit(ctxt int, pass int, n *Node, var_ *Node, init *Nodes) {
|
2016-03-08 15:10:26 -08:00
|
|
|
for _, r := range n.List.Slice() {
|
2015-02-13 14:40:36 -05:00
|
|
|
if r.Op != OKEY {
|
2015-08-30 23:10:03 +02:00
|
|
|
Fatalf("arraylit: rhs not OKEY: %v", r)
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
2015-09-08 22:22:44 +02:00
|
|
|
index := r.Left
|
|
|
|
|
value := r.Right
|
|
|
|
|
|
2015-02-13 14:40:36 -05:00
|
|
|
switch value.Op {
|
|
|
|
|
case OARRAYLIT:
|
2016-03-29 09:14:19 -07:00
|
|
|
if value.Type.IsSlice() {
|
2015-02-13 14:40:36 -05:00
|
|
|
if pass == 1 && ctxt != 0 {
|
2016-03-24 20:57:53 +11:00
|
|
|
a := Nod(OINDEX, var_, index)
|
2015-02-13 14:40:36 -05:00
|
|
|
slicelit(ctxt, value, a, init)
|
|
|
|
|
} else if pass == 2 && ctxt == 0 {
|
2016-03-24 20:57:53 +11:00
|
|
|
a := Nod(OINDEX, var_, index)
|
2015-02-13 14:40:36 -05:00
|
|
|
slicelit(ctxt, value, a, init)
|
|
|
|
|
} else if pass == 3 {
|
|
|
|
|
break
|
|
|
|
|
}
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
|
2016-03-24 20:57:53 +11:00
|
|
|
a := Nod(OINDEX, var_, index)
|
2015-02-13 14:40:36 -05:00
|
|
|
arraylit(ctxt, pass, value, a, init)
|
|
|
|
|
continue
|
|
|
|
|
|
|
|
|
|
case OSTRUCTLIT:
|
2016-03-24 20:57:53 +11:00
|
|
|
a := Nod(OINDEX, var_, index)
|
2015-02-13 14:40:36 -05:00
|
|
|
structlit(ctxt, pass, value, a, init)
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
|
2015-02-17 22:13:49 -05:00
|
|
|
if isliteral(index) && isliteral(value) {
|
2015-02-13 14:40:36 -05:00
|
|
|
if pass == 2 {
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
} else if pass == 1 {
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// build list of var[index] = value
|
2015-06-29 16:30:19 -04:00
|
|
|
setlineno(value)
|
2016-03-24 20:57:53 +11:00
|
|
|
a := Nod(OINDEX, var_, index)
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
|
a = Nod(OAS, a, value)
|
cmd/compile: reduce use of **Node parameters
Escape analysis has a hard time with tree-like
structures (see #13493 and #14858).
This is unlikely to change.
As a result, when invoking a function that accepts
a **Node parameter, we usually allocate a *Node
on the heap. This happens a whole lot.
This CL changes functions from taking a **Node
to acting more like append: It both modifies
the input and returns a replacement for it.
Because of the cascading nature of escape analysis,
in order to get the benefits, I had to modify
almost all such functions. The remaining functions
are in racewalk and the backend. I would be happy
to update them as well in a separate CL.
This CL was created by manually updating the
function signatures and the directly impacted
bits of code. The callsites were then automatically
updated using a bespoke script:
https://gist.github.com/josharian/046b1be7aceae244de39
For ease of reviewing and future understanding,
this CL is also broken down into four CLs,
mailed separately, which show the manual
and the automated changes separately.
They are CLs 20990, 20991, 20992, and 20993.
Passes toolstash -cmp.
name old time/op new time/op delta
Template 335ms ± 5% 324ms ± 5% -3.35% (p=0.000 n=23+24)
Unicode 176ms ± 9% 165ms ± 6% -6.12% (p=0.000 n=23+24)
GoTypes 1.10s ± 4% 1.07s ± 2% -2.77% (p=0.000 n=24+24)
Compiler 5.31s ± 3% 5.15s ± 3% -2.95% (p=0.000 n=24+24)
MakeBash 41.6s ± 1% 41.7s ± 2% ~ (p=0.586 n=23+23)
name old alloc/op new alloc/op delta
Template 63.3MB ± 0% 62.4MB ± 0% -1.36% (p=0.000 n=25+23)
Unicode 42.4MB ± 0% 41.6MB ± 0% -1.99% (p=0.000 n=24+25)
GoTypes 220MB ± 0% 217MB ± 0% -1.11% (p=0.000 n=25+25)
Compiler 994MB ± 0% 973MB ± 0% -2.08% (p=0.000 n=24+25)
name old allocs/op new allocs/op delta
Template 681k ± 0% 574k ± 0% -15.71% (p=0.000 n=24+25)
Unicode 518k ± 0% 413k ± 0% -20.34% (p=0.000 n=25+24)
GoTypes 2.08M ± 0% 1.78M ± 0% -14.62% (p=0.000 n=25+25)
Compiler 9.26M ± 0% 7.64M ± 0% -17.48% (p=0.000 n=25+25)
name old text-bytes new text-bytes delta
HelloSize 578k ± 0% 578k ± 0% ~ (all samples are equal)
CmdGoSize 6.46M ± 0% 6.46M ± 0% ~ (all samples are equal)
name old data-bytes new data-bytes delta
HelloSize 128k ± 0% 128k ± 0% ~ (all samples are equal)
CmdGoSize 281k ± 0% 281k ± 0% ~ (all samples are equal)
name old exe-bytes new exe-bytes delta
HelloSize 921k ± 0% 921k ± 0% ~ (all samples are equal)
CmdGoSize 9.86M ± 0% 9.86M ± 0% ~ (all samples are equal)
Change-Id: I277d95bd56d51c166ef7f560647aeaa092f3f475
Reviewed-on: https://go-review.googlesource.com/20959
Reviewed-by: Dave Cheney <dave@cheney.net>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
2016-03-20 08:03:31 -07:00
|
|
|
a = typecheck(a, Etop)
|
2015-02-13 14:40:36 -05:00
|
|
|
if pass == 1 {
|
cmd/compile: reduce use of **Node parameters
Escape analysis has a hard time with tree-like
structures (see #13493 and #14858).
This is unlikely to change.
As a result, when invoking a function that accepts
a **Node parameter, we usually allocate a *Node
on the heap. This happens a whole lot.
This CL changes functions from taking a **Node
to acting more like append: It both modifies
the input and returns a replacement for it.
Because of the cascading nature of escape analysis,
in order to get the benefits, I had to modify
almost all such functions. The remaining functions
are in racewalk and the backend. I would be happy
to update them as well in a separate CL.
This CL was created by manually updating the
function signatures and the directly impacted
bits of code. The callsites were then automatically
updated using a bespoke script:
https://gist.github.com/josharian/046b1be7aceae244de39
For ease of reviewing and future understanding,
this CL is also broken down into four CLs,
mailed separately, which show the manual
and the automated changes separately.
They are CLs 20990, 20991, 20992, and 20993.
Passes toolstash -cmp.
name old time/op new time/op delta
Template 335ms ± 5% 324ms ± 5% -3.35% (p=0.000 n=23+24)
Unicode 176ms ± 9% 165ms ± 6% -6.12% (p=0.000 n=23+24)
GoTypes 1.10s ± 4% 1.07s ± 2% -2.77% (p=0.000 n=24+24)
Compiler 5.31s ± 3% 5.15s ± 3% -2.95% (p=0.000 n=24+24)
MakeBash 41.6s ± 1% 41.7s ± 2% ~ (p=0.586 n=23+23)
name old alloc/op new alloc/op delta
Template 63.3MB ± 0% 62.4MB ± 0% -1.36% (p=0.000 n=25+23)
Unicode 42.4MB ± 0% 41.6MB ± 0% -1.99% (p=0.000 n=24+25)
GoTypes 220MB ± 0% 217MB ± 0% -1.11% (p=0.000 n=25+25)
Compiler 994MB ± 0% 973MB ± 0% -2.08% (p=0.000 n=24+25)
name old allocs/op new allocs/op delta
Template 681k ± 0% 574k ± 0% -15.71% (p=0.000 n=24+25)
Unicode 518k ± 0% 413k ± 0% -20.34% (p=0.000 n=25+24)
GoTypes 2.08M ± 0% 1.78M ± 0% -14.62% (p=0.000 n=25+25)
Compiler 9.26M ± 0% 7.64M ± 0% -17.48% (p=0.000 n=25+25)
name old text-bytes new text-bytes delta
HelloSize 578k ± 0% 578k ± 0% ~ (all samples are equal)
CmdGoSize 6.46M ± 0% 6.46M ± 0% ~ (all samples are equal)
name old data-bytes new data-bytes delta
HelloSize 128k ± 0% 128k ± 0% ~ (all samples are equal)
CmdGoSize 281k ± 0% 281k ± 0% ~ (all samples are equal)
name old exe-bytes new exe-bytes delta
HelloSize 921k ± 0% 921k ± 0% ~ (all samples are equal)
CmdGoSize 9.86M ± 0% 9.86M ± 0% ~ (all samples are equal)
Change-Id: I277d95bd56d51c166ef7f560647aeaa092f3f475
Reviewed-on: https://go-review.googlesource.com/20959
Reviewed-by: Dave Cheney <dave@cheney.net>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
2016-03-20 08:03:31 -07:00
|
|
|
a = walkexpr(a, init)
|
2015-02-13 14:40:36 -05:00
|
|
|
if a.Op != OAS {
|
2015-08-30 23:10:03 +02:00
|
|
|
Fatalf("arraylit: not as")
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
2016-05-16 14:23:12 -07:00
|
|
|
a.IsStatic = true
|
2015-02-13 14:40:36 -05:00
|
|
|
} else {
|
cmd/compile: reduce use of **Node parameters
Escape analysis has a hard time with tree-like
structures (see #13493 and #14858).
This is unlikely to change.
As a result, when invoking a function that accepts
a **Node parameter, we usually allocate a *Node
on the heap. This happens a whole lot.
This CL changes functions from taking a **Node
to acting more like append: It both modifies
the input and returns a replacement for it.
Because of the cascading nature of escape analysis,
in order to get the benefits, I had to modify
almost all such functions. The remaining functions
are in racewalk and the backend. I would be happy
to update them as well in a separate CL.
This CL was created by manually updating the
function signatures and the directly impacted
bits of code. The callsites were then automatically
updated using a bespoke script:
https://gist.github.com/josharian/046b1be7aceae244de39
For ease of reviewing and future understanding,
this CL is also broken down into four CLs,
mailed separately, which show the manual
and the automated changes separately.
They are CLs 20990, 20991, 20992, and 20993.
Passes toolstash -cmp.
name old time/op new time/op delta
Template 335ms ± 5% 324ms ± 5% -3.35% (p=0.000 n=23+24)
Unicode 176ms ± 9% 165ms ± 6% -6.12% (p=0.000 n=23+24)
GoTypes 1.10s ± 4% 1.07s ± 2% -2.77% (p=0.000 n=24+24)
Compiler 5.31s ± 3% 5.15s ± 3% -2.95% (p=0.000 n=24+24)
MakeBash 41.6s ± 1% 41.7s ± 2% ~ (p=0.586 n=23+23)
name old alloc/op new alloc/op delta
Template 63.3MB ± 0% 62.4MB ± 0% -1.36% (p=0.000 n=25+23)
Unicode 42.4MB ± 0% 41.6MB ± 0% -1.99% (p=0.000 n=24+25)
GoTypes 220MB ± 0% 217MB ± 0% -1.11% (p=0.000 n=25+25)
Compiler 994MB ± 0% 973MB ± 0% -2.08% (p=0.000 n=24+25)
name old allocs/op new allocs/op delta
Template 681k ± 0% 574k ± 0% -15.71% (p=0.000 n=24+25)
Unicode 518k ± 0% 413k ± 0% -20.34% (p=0.000 n=25+24)
GoTypes 2.08M ± 0% 1.78M ± 0% -14.62% (p=0.000 n=25+25)
Compiler 9.26M ± 0% 7.64M ± 0% -17.48% (p=0.000 n=25+25)
name old text-bytes new text-bytes delta
HelloSize 578k ± 0% 578k ± 0% ~ (all samples are equal)
CmdGoSize 6.46M ± 0% 6.46M ± 0% ~ (all samples are equal)
name old data-bytes new data-bytes delta
HelloSize 128k ± 0% 128k ± 0% ~ (all samples are equal)
CmdGoSize 281k ± 0% 281k ± 0% ~ (all samples are equal)
name old exe-bytes new exe-bytes delta
HelloSize 921k ± 0% 921k ± 0% ~ (all samples are equal)
CmdGoSize 9.86M ± 0% 9.86M ± 0% ~ (all samples are equal)
Change-Id: I277d95bd56d51c166ef7f560647aeaa092f3f475
Reviewed-on: https://go-review.googlesource.com/20959
Reviewed-by: Dave Cheney <dave@cheney.net>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
2016-03-20 08:03:31 -07:00
|
|
|
a = orderstmtinplace(a)
|
|
|
|
|
a = walkstmt(a)
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
2016-03-07 22:54:46 -08:00
|
|
|
init.Append(a)
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2016-03-07 22:54:46 -08:00
|
|
|
func slicelit(ctxt int, n *Node, var_ *Node, init *Nodes) {
|
2016-03-31 15:18:39 -07:00
|
|
|
// make an array type corresponding the number of elements we have
|
2016-04-01 14:51:02 -07:00
|
|
|
t := typArray(n.Type.Elem(), n.Right.Int64())
|
2015-02-13 14:40:36 -05:00
|
|
|
dowidth(t)
|
|
|
|
|
|
|
|
|
|
if ctxt != 0 {
|
|
|
|
|
// put everything into static array
|
2015-02-23 16:07:24 -05:00
|
|
|
vstat := staticname(t, ctxt)
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
|
arraylit(ctxt, 1, n, vstat, init)
|
|
|
|
|
arraylit(ctxt, 2, n, vstat, init)
|
|
|
|
|
|
|
|
|
|
// copy static to slice
|
2016-04-21 11:55:33 -07:00
|
|
|
a := Nod(OSLICE, vstat, nil)
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
|
a = Nod(OAS, var_, a)
|
cmd/compile: reduce use of **Node parameters
Escape analysis has a hard time with tree-like
structures (see #13493 and #14858).
This is unlikely to change.
As a result, when invoking a function that accepts
a **Node parameter, we usually allocate a *Node
on the heap. This happens a whole lot.
This CL changes functions from taking a **Node
to acting more like append: It both modifies
the input and returns a replacement for it.
Because of the cascading nature of escape analysis,
in order to get the benefits, I had to modify
almost all such functions. The remaining functions
are in racewalk and the backend. I would be happy
to update them as well in a separate CL.
This CL was created by manually updating the
function signatures and the directly impacted
bits of code. The callsites were then automatically
updated using a bespoke script:
https://gist.github.com/josharian/046b1be7aceae244de39
For ease of reviewing and future understanding,
this CL is also broken down into four CLs,
mailed separately, which show the manual
and the automated changes separately.
They are CLs 20990, 20991, 20992, and 20993.
Passes toolstash -cmp.
name old time/op new time/op delta
Template 335ms ± 5% 324ms ± 5% -3.35% (p=0.000 n=23+24)
Unicode 176ms ± 9% 165ms ± 6% -6.12% (p=0.000 n=23+24)
GoTypes 1.10s ± 4% 1.07s ± 2% -2.77% (p=0.000 n=24+24)
Compiler 5.31s ± 3% 5.15s ± 3% -2.95% (p=0.000 n=24+24)
MakeBash 41.6s ± 1% 41.7s ± 2% ~ (p=0.586 n=23+23)
name old alloc/op new alloc/op delta
Template 63.3MB ± 0% 62.4MB ± 0% -1.36% (p=0.000 n=25+23)
Unicode 42.4MB ± 0% 41.6MB ± 0% -1.99% (p=0.000 n=24+25)
GoTypes 220MB ± 0% 217MB ± 0% -1.11% (p=0.000 n=25+25)
Compiler 994MB ± 0% 973MB ± 0% -2.08% (p=0.000 n=24+25)
name old allocs/op new allocs/op delta
Template 681k ± 0% 574k ± 0% -15.71% (p=0.000 n=24+25)
Unicode 518k ± 0% 413k ± 0% -20.34% (p=0.000 n=25+24)
GoTypes 2.08M ± 0% 1.78M ± 0% -14.62% (p=0.000 n=25+25)
Compiler 9.26M ± 0% 7.64M ± 0% -17.48% (p=0.000 n=25+25)
name old text-bytes new text-bytes delta
HelloSize 578k ± 0% 578k ± 0% ~ (all samples are equal)
CmdGoSize 6.46M ± 0% 6.46M ± 0% ~ (all samples are equal)
name old data-bytes new data-bytes delta
HelloSize 128k ± 0% 128k ± 0% ~ (all samples are equal)
CmdGoSize 281k ± 0% 281k ± 0% ~ (all samples are equal)
name old exe-bytes new exe-bytes delta
HelloSize 921k ± 0% 921k ± 0% ~ (all samples are equal)
CmdGoSize 9.86M ± 0% 9.86M ± 0% ~ (all samples are equal)
Change-Id: I277d95bd56d51c166ef7f560647aeaa092f3f475
Reviewed-on: https://go-review.googlesource.com/20959
Reviewed-by: Dave Cheney <dave@cheney.net>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
2016-03-20 08:03:31 -07:00
|
|
|
a = typecheck(a, Etop)
|
2016-05-16 14:23:12 -07:00
|
|
|
a.IsStatic = true
|
2016-03-07 22:54:46 -08:00
|
|
|
init.Append(a)
|
2015-02-13 14:40:36 -05:00
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// recipe for var = []t{...}
|
|
|
|
|
// 1. make a static array
|
|
|
|
|
// var vstat [...]t
|
|
|
|
|
// 2. assign (data statements) the constant part
|
|
|
|
|
// vstat = constpart{}
|
|
|
|
|
// 3. make an auto pointer to array and allocate heap to it
|
|
|
|
|
// var vauto *[...]t = new([...]t)
|
|
|
|
|
// 4. copy the static array to the auto array
|
|
|
|
|
// *vauto = vstat
|
2016-04-23 22:59:01 -07:00
|
|
|
// 5. for each dynamic part assign to the array
|
|
|
|
|
// vauto[i] = dynamic part
|
|
|
|
|
// 6. assign slice of allocated heap to var
|
|
|
|
|
// var = vauto[:]
|
2015-02-13 14:40:36 -05:00
|
|
|
//
|
|
|
|
|
// an optimization is done if there is no constant part
|
|
|
|
|
// 3. var vauto *[...]t = new([...]t)
|
2016-04-23 22:59:01 -07:00
|
|
|
// 5. vauto[i] = dynamic part
|
|
|
|
|
// 6. var = vauto[:]
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
|
// if the literal contains constants,
|
|
|
|
|
// make static initialized array (1),(2)
|
2015-03-02 14:22:05 -05:00
|
|
|
var vstat *Node
|
2015-02-13 14:40:36 -05:00
|
|
|
|
2016-05-16 14:28:44 -07:00
|
|
|
mode := getdyn(n, true)
|
2016-03-13 17:06:10 -07:00
|
|
|
if mode&initConst != 0 {
|
2015-02-13 14:40:36 -05:00
|
|
|
vstat = staticname(t, ctxt)
|
|
|
|
|
arraylit(ctxt, 1, n, vstat, init)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// make new auto *array (3 declare)
|
2015-02-23 16:07:24 -05:00
|
|
|
vauto := temp(Ptrto(t))
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
|
// set auto to point at new temp or heap (3 assign)
|
2015-02-23 16:07:24 -05:00
|
|
|
var a *Node
|
2015-05-26 23:05:35 -04:00
|
|
|
if x := prealloc[n]; x != nil {
|
2015-10-22 09:51:12 +09:00
|
|
|
// temp allocated during order.go for dddarg
|
2015-05-26 23:05:35 -04:00
|
|
|
x.Type = t
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
|
if vstat == nil {
|
2015-05-26 23:05:35 -04:00
|
|
|
a = Nod(OAS, x, nil)
|
cmd/compile: reduce use of **Node parameters
Escape analysis has a hard time with tree-like
structures (see #13493 and #14858).
This is unlikely to change.
As a result, when invoking a function that accepts
a **Node parameter, we usually allocate a *Node
on the heap. This happens a whole lot.
This CL changes functions from taking a **Node
to acting more like append: It both modifies
the input and returns a replacement for it.
Because of the cascading nature of escape analysis,
in order to get the benefits, I had to modify
almost all such functions. The remaining functions
are in racewalk and the backend. I would be happy
to update them as well in a separate CL.
This CL was created by manually updating the
function signatures and the directly impacted
bits of code. The callsites were then automatically
updated using a bespoke script:
https://gist.github.com/josharian/046b1be7aceae244de39
For ease of reviewing and future understanding,
this CL is also broken down into four CLs,
mailed separately, which show the manual
and the automated changes separately.
They are CLs 20990, 20991, 20992, and 20993.
Passes toolstash -cmp.
name old time/op new time/op delta
Template 335ms ± 5% 324ms ± 5% -3.35% (p=0.000 n=23+24)
Unicode 176ms ± 9% 165ms ± 6% -6.12% (p=0.000 n=23+24)
GoTypes 1.10s ± 4% 1.07s ± 2% -2.77% (p=0.000 n=24+24)
Compiler 5.31s ± 3% 5.15s ± 3% -2.95% (p=0.000 n=24+24)
MakeBash 41.6s ± 1% 41.7s ± 2% ~ (p=0.586 n=23+23)
name old alloc/op new alloc/op delta
Template 63.3MB ± 0% 62.4MB ± 0% -1.36% (p=0.000 n=25+23)
Unicode 42.4MB ± 0% 41.6MB ± 0% -1.99% (p=0.000 n=24+25)
GoTypes 220MB ± 0% 217MB ± 0% -1.11% (p=0.000 n=25+25)
Compiler 994MB ± 0% 973MB ± 0% -2.08% (p=0.000 n=24+25)
name old allocs/op new allocs/op delta
Template 681k ± 0% 574k ± 0% -15.71% (p=0.000 n=24+25)
Unicode 518k ± 0% 413k ± 0% -20.34% (p=0.000 n=25+24)
GoTypes 2.08M ± 0% 1.78M ± 0% -14.62% (p=0.000 n=25+25)
Compiler 9.26M ± 0% 7.64M ± 0% -17.48% (p=0.000 n=25+25)
name old text-bytes new text-bytes delta
HelloSize 578k ± 0% 578k ± 0% ~ (all samples are equal)
CmdGoSize 6.46M ± 0% 6.46M ± 0% ~ (all samples are equal)
name old data-bytes new data-bytes delta
HelloSize 128k ± 0% 128k ± 0% ~ (all samples are equal)
CmdGoSize 281k ± 0% 281k ± 0% ~ (all samples are equal)
name old exe-bytes new exe-bytes delta
HelloSize 921k ± 0% 921k ± 0% ~ (all samples are equal)
CmdGoSize 9.86M ± 0% 9.86M ± 0% ~ (all samples are equal)
Change-Id: I277d95bd56d51c166ef7f560647aeaa092f3f475
Reviewed-on: https://go-review.googlesource.com/20959
Reviewed-by: Dave Cheney <dave@cheney.net>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
2016-03-20 08:03:31 -07:00
|
|
|
a = typecheck(a, Etop)
|
2016-03-07 22:54:46 -08:00
|
|
|
init.Append(a) // zero new temp
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
2015-05-26 23:05:35 -04:00
|
|
|
a = Nod(OADDR, x, nil)
|
2015-02-13 14:40:36 -05:00
|
|
|
} else if n.Esc == EscNone {
|
|
|
|
|
a = temp(t)
|
|
|
|
|
if vstat == nil {
|
|
|
|
|
a = Nod(OAS, temp(t), nil)
|
cmd/compile: reduce use of **Node parameters
Escape analysis has a hard time with tree-like
structures (see #13493 and #14858).
This is unlikely to change.
As a result, when invoking a function that accepts
a **Node parameter, we usually allocate a *Node
on the heap. This happens a whole lot.
This CL changes functions from taking a **Node
to acting more like append: It both modifies
the input and returns a replacement for it.
Because of the cascading nature of escape analysis,
in order to get the benefits, I had to modify
almost all such functions. The remaining functions
are in racewalk and the backend. I would be happy
to update them as well in a separate CL.
This CL was created by manually updating the
function signatures and the directly impacted
bits of code. The callsites were then automatically
updated using a bespoke script:
https://gist.github.com/josharian/046b1be7aceae244de39
For ease of reviewing and future understanding,
this CL is also broken down into four CLs,
mailed separately, which show the manual
and the automated changes separately.
They are CLs 20990, 20991, 20992, and 20993.
Passes toolstash -cmp.
name old time/op new time/op delta
Template 335ms ± 5% 324ms ± 5% -3.35% (p=0.000 n=23+24)
Unicode 176ms ± 9% 165ms ± 6% -6.12% (p=0.000 n=23+24)
GoTypes 1.10s ± 4% 1.07s ± 2% -2.77% (p=0.000 n=24+24)
Compiler 5.31s ± 3% 5.15s ± 3% -2.95% (p=0.000 n=24+24)
MakeBash 41.6s ± 1% 41.7s ± 2% ~ (p=0.586 n=23+23)
name old alloc/op new alloc/op delta
Template 63.3MB ± 0% 62.4MB ± 0% -1.36% (p=0.000 n=25+23)
Unicode 42.4MB ± 0% 41.6MB ± 0% -1.99% (p=0.000 n=24+25)
GoTypes 220MB ± 0% 217MB ± 0% -1.11% (p=0.000 n=25+25)
Compiler 994MB ± 0% 973MB ± 0% -2.08% (p=0.000 n=24+25)
name old allocs/op new allocs/op delta
Template 681k ± 0% 574k ± 0% -15.71% (p=0.000 n=24+25)
Unicode 518k ± 0% 413k ± 0% -20.34% (p=0.000 n=25+24)
GoTypes 2.08M ± 0% 1.78M ± 0% -14.62% (p=0.000 n=25+25)
Compiler 9.26M ± 0% 7.64M ± 0% -17.48% (p=0.000 n=25+25)
name old text-bytes new text-bytes delta
HelloSize 578k ± 0% 578k ± 0% ~ (all samples are equal)
CmdGoSize 6.46M ± 0% 6.46M ± 0% ~ (all samples are equal)
name old data-bytes new data-bytes delta
HelloSize 128k ± 0% 128k ± 0% ~ (all samples are equal)
CmdGoSize 281k ± 0% 281k ± 0% ~ (all samples are equal)
name old exe-bytes new exe-bytes delta
HelloSize 921k ± 0% 921k ± 0% ~ (all samples are equal)
CmdGoSize 9.86M ± 0% 9.86M ± 0% ~ (all samples are equal)
Change-Id: I277d95bd56d51c166ef7f560647aeaa092f3f475
Reviewed-on: https://go-review.googlesource.com/20959
Reviewed-by: Dave Cheney <dave@cheney.net>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
2016-03-20 08:03:31 -07:00
|
|
|
a = typecheck(a, Etop)
|
2016-03-07 22:54:46 -08:00
|
|
|
init.Append(a) // zero new temp
|
2015-02-13 14:40:36 -05:00
|
|
|
a = a.Left
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
a = Nod(OADDR, a, nil)
|
|
|
|
|
} else {
|
|
|
|
|
a = Nod(ONEW, nil, nil)
|
2016-03-10 10:13:42 -08:00
|
|
|
a.List.Set1(typenod(t))
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
a = Nod(OAS, vauto, a)
|
cmd/compile: reduce use of **Node parameters
Escape analysis has a hard time with tree-like
structures (see #13493 and #14858).
This is unlikely to change.
As a result, when invoking a function that accepts
a **Node parameter, we usually allocate a *Node
on the heap. This happens a whole lot.
This CL changes functions from taking a **Node
to acting more like append: It both modifies
the input and returns a replacement for it.
Because of the cascading nature of escape analysis,
in order to get the benefits, I had to modify
almost all such functions. The remaining functions
are in racewalk and the backend. I would be happy
to update them as well in a separate CL.
This CL was created by manually updating the
function signatures and the directly impacted
bits of code. The callsites were then automatically
updated using a bespoke script:
https://gist.github.com/josharian/046b1be7aceae244de39
For ease of reviewing and future understanding,
this CL is also broken down into four CLs,
mailed separately, which show the manual
and the automated changes separately.
They are CLs 20990, 20991, 20992, and 20993.
Passes toolstash -cmp.
name old time/op new time/op delta
Template 335ms ± 5% 324ms ± 5% -3.35% (p=0.000 n=23+24)
Unicode 176ms ± 9% 165ms ± 6% -6.12% (p=0.000 n=23+24)
GoTypes 1.10s ± 4% 1.07s ± 2% -2.77% (p=0.000 n=24+24)
Compiler 5.31s ± 3% 5.15s ± 3% -2.95% (p=0.000 n=24+24)
MakeBash 41.6s ± 1% 41.7s ± 2% ~ (p=0.586 n=23+23)
name old alloc/op new alloc/op delta
Template 63.3MB ± 0% 62.4MB ± 0% -1.36% (p=0.000 n=25+23)
Unicode 42.4MB ± 0% 41.6MB ± 0% -1.99% (p=0.000 n=24+25)
GoTypes 220MB ± 0% 217MB ± 0% -1.11% (p=0.000 n=25+25)
Compiler 994MB ± 0% 973MB ± 0% -2.08% (p=0.000 n=24+25)
name old allocs/op new allocs/op delta
Template 681k ± 0% 574k ± 0% -15.71% (p=0.000 n=24+25)
Unicode 518k ± 0% 413k ± 0% -20.34% (p=0.000 n=25+24)
GoTypes 2.08M ± 0% 1.78M ± 0% -14.62% (p=0.000 n=25+25)
Compiler 9.26M ± 0% 7.64M ± 0% -17.48% (p=0.000 n=25+25)
name old text-bytes new text-bytes delta
HelloSize 578k ± 0% 578k ± 0% ~ (all samples are equal)
CmdGoSize 6.46M ± 0% 6.46M ± 0% ~ (all samples are equal)
name old data-bytes new data-bytes delta
HelloSize 128k ± 0% 128k ± 0% ~ (all samples are equal)
CmdGoSize 281k ± 0% 281k ± 0% ~ (all samples are equal)
name old exe-bytes new exe-bytes delta
HelloSize 921k ± 0% 921k ± 0% ~ (all samples are equal)
CmdGoSize 9.86M ± 0% 9.86M ± 0% ~ (all samples are equal)
Change-Id: I277d95bd56d51c166ef7f560647aeaa092f3f475
Reviewed-on: https://go-review.googlesource.com/20959
Reviewed-by: Dave Cheney <dave@cheney.net>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
2016-03-20 08:03:31 -07:00
|
|
|
a = typecheck(a, Etop)
|
|
|
|
|
a = walkexpr(a, init)
|
2016-03-07 22:54:46 -08:00
|
|
|
init.Append(a)
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
|
if vstat != nil {
|
|
|
|
|
// copy static to heap (4)
|
|
|
|
|
a = Nod(OIND, vauto, nil)
|
|
|
|
|
|
|
|
|
|
a = Nod(OAS, a, vstat)
|
cmd/compile: reduce use of **Node parameters
Escape analysis has a hard time with tree-like
structures (see #13493 and #14858).
This is unlikely to change.
As a result, when invoking a function that accepts
a **Node parameter, we usually allocate a *Node
on the heap. This happens a whole lot.
This CL changes functions from taking a **Node
to acting more like append: It both modifies
the input and returns a replacement for it.
Because of the cascading nature of escape analysis,
in order to get the benefits, I had to modify
almost all such functions. The remaining functions
are in racewalk and the backend. I would be happy
to update them as well in a separate CL.
This CL was created by manually updating the
function signatures and the directly impacted
bits of code. The callsites were then automatically
updated using a bespoke script:
https://gist.github.com/josharian/046b1be7aceae244de39
For ease of reviewing and future understanding,
this CL is also broken down into four CLs,
mailed separately, which show the manual
and the automated changes separately.
They are CLs 20990, 20991, 20992, and 20993.
Passes toolstash -cmp.
name old time/op new time/op delta
Template 335ms ± 5% 324ms ± 5% -3.35% (p=0.000 n=23+24)
Unicode 176ms ± 9% 165ms ± 6% -6.12% (p=0.000 n=23+24)
GoTypes 1.10s ± 4% 1.07s ± 2% -2.77% (p=0.000 n=24+24)
Compiler 5.31s ± 3% 5.15s ± 3% -2.95% (p=0.000 n=24+24)
MakeBash 41.6s ± 1% 41.7s ± 2% ~ (p=0.586 n=23+23)
name old alloc/op new alloc/op delta
Template 63.3MB ± 0% 62.4MB ± 0% -1.36% (p=0.000 n=25+23)
Unicode 42.4MB ± 0% 41.6MB ± 0% -1.99% (p=0.000 n=24+25)
GoTypes 220MB ± 0% 217MB ± 0% -1.11% (p=0.000 n=25+25)
Compiler 994MB ± 0% 973MB ± 0% -2.08% (p=0.000 n=24+25)
name old allocs/op new allocs/op delta
Template 681k ± 0% 574k ± 0% -15.71% (p=0.000 n=24+25)
Unicode 518k ± 0% 413k ± 0% -20.34% (p=0.000 n=25+24)
GoTypes 2.08M ± 0% 1.78M ± 0% -14.62% (p=0.000 n=25+25)
Compiler 9.26M ± 0% 7.64M ± 0% -17.48% (p=0.000 n=25+25)
name old text-bytes new text-bytes delta
HelloSize 578k ± 0% 578k ± 0% ~ (all samples are equal)
CmdGoSize 6.46M ± 0% 6.46M ± 0% ~ (all samples are equal)
name old data-bytes new data-bytes delta
HelloSize 128k ± 0% 128k ± 0% ~ (all samples are equal)
CmdGoSize 281k ± 0% 281k ± 0% ~ (all samples are equal)
name old exe-bytes new exe-bytes delta
HelloSize 921k ± 0% 921k ± 0% ~ (all samples are equal)
CmdGoSize 9.86M ± 0% 9.86M ± 0% ~ (all samples are equal)
Change-Id: I277d95bd56d51c166ef7f560647aeaa092f3f475
Reviewed-on: https://go-review.googlesource.com/20959
Reviewed-by: Dave Cheney <dave@cheney.net>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
2016-03-20 08:03:31 -07:00
|
|
|
a = typecheck(a, Etop)
|
|
|
|
|
a = walkexpr(a, init)
|
2016-03-07 22:54:46 -08:00
|
|
|
init.Append(a)
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
2016-04-23 22:59:01 -07:00
|
|
|
// put dynamics into array (5)
|
2016-03-08 15:10:26 -08:00
|
|
|
for _, r := range n.List.Slice() {
|
2015-02-13 14:40:36 -05:00
|
|
|
if r.Op != OKEY {
|
2015-08-30 23:10:03 +02:00
|
|
|
Fatalf("slicelit: rhs not OKEY: %v", r)
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
2015-09-08 22:22:44 +02:00
|
|
|
index := r.Left
|
|
|
|
|
value := r.Right
|
2016-04-23 22:59:01 -07:00
|
|
|
a := Nod(OINDEX, vauto, index)
|
2015-02-17 22:13:49 -05:00
|
|
|
a.Bounded = true
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
|
// TODO need to check bounds?
|
|
|
|
|
|
|
|
|
|
switch value.Op {
|
|
|
|
|
case OARRAYLIT:
|
2016-03-29 09:14:19 -07:00
|
|
|
if value.Type.IsSlice() {
|
2015-02-13 14:40:36 -05:00
|
|
|
break
|
|
|
|
|
}
|
|
|
|
|
arraylit(ctxt, 2, value, a, init)
|
|
|
|
|
continue
|
|
|
|
|
|
|
|
|
|
case OSTRUCTLIT:
|
|
|
|
|
structlit(ctxt, 2, value, a, init)
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
|
2015-02-17 22:13:49 -05:00
|
|
|
if isliteral(index) && isliteral(value) {
|
2015-02-13 14:40:36 -05:00
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
|
2016-04-23 22:59:01 -07:00
|
|
|
// build list of vauto[c] = expr
|
2015-06-29 16:30:19 -04:00
|
|
|
setlineno(value)
|
2015-02-13 14:40:36 -05:00
|
|
|
a = Nod(OAS, a, value)
|
|
|
|
|
|
cmd/compile: reduce use of **Node parameters
Escape analysis has a hard time with tree-like
structures (see #13493 and #14858).
This is unlikely to change.
As a result, when invoking a function that accepts
a **Node parameter, we usually allocate a *Node
on the heap. This happens a whole lot.
This CL changes functions from taking a **Node
to acting more like append: It both modifies
the input and returns a replacement for it.
Because of the cascading nature of escape analysis,
in order to get the benefits, I had to modify
almost all such functions. The remaining functions
are in racewalk and the backend. I would be happy
to update them as well in a separate CL.
This CL was created by manually updating the
function signatures and the directly impacted
bits of code. The callsites were then automatically
updated using a bespoke script:
https://gist.github.com/josharian/046b1be7aceae244de39
For ease of reviewing and future understanding,
this CL is also broken down into four CLs,
mailed separately, which show the manual
and the automated changes separately.
They are CLs 20990, 20991, 20992, and 20993.
Passes toolstash -cmp.
name old time/op new time/op delta
Template 335ms ± 5% 324ms ± 5% -3.35% (p=0.000 n=23+24)
Unicode 176ms ± 9% 165ms ± 6% -6.12% (p=0.000 n=23+24)
GoTypes 1.10s ± 4% 1.07s ± 2% -2.77% (p=0.000 n=24+24)
Compiler 5.31s ± 3% 5.15s ± 3% -2.95% (p=0.000 n=24+24)
MakeBash 41.6s ± 1% 41.7s ± 2% ~ (p=0.586 n=23+23)
name old alloc/op new alloc/op delta
Template 63.3MB ± 0% 62.4MB ± 0% -1.36% (p=0.000 n=25+23)
Unicode 42.4MB ± 0% 41.6MB ± 0% -1.99% (p=0.000 n=24+25)
GoTypes 220MB ± 0% 217MB ± 0% -1.11% (p=0.000 n=25+25)
Compiler 994MB ± 0% 973MB ± 0% -2.08% (p=0.000 n=24+25)
name old allocs/op new allocs/op delta
Template 681k ± 0% 574k ± 0% -15.71% (p=0.000 n=24+25)
Unicode 518k ± 0% 413k ± 0% -20.34% (p=0.000 n=25+24)
GoTypes 2.08M ± 0% 1.78M ± 0% -14.62% (p=0.000 n=25+25)
Compiler 9.26M ± 0% 7.64M ± 0% -17.48% (p=0.000 n=25+25)
name old text-bytes new text-bytes delta
HelloSize 578k ± 0% 578k ± 0% ~ (all samples are equal)
CmdGoSize 6.46M ± 0% 6.46M ± 0% ~ (all samples are equal)
name old data-bytes new data-bytes delta
HelloSize 128k ± 0% 128k ± 0% ~ (all samples are equal)
CmdGoSize 281k ± 0% 281k ± 0% ~ (all samples are equal)
name old exe-bytes new exe-bytes delta
HelloSize 921k ± 0% 921k ± 0% ~ (all samples are equal)
CmdGoSize 9.86M ± 0% 9.86M ± 0% ~ (all samples are equal)
Change-Id: I277d95bd56d51c166ef7f560647aeaa092f3f475
Reviewed-on: https://go-review.googlesource.com/20959
Reviewed-by: Dave Cheney <dave@cheney.net>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
2016-03-20 08:03:31 -07:00
|
|
|
a = typecheck(a, Etop)
|
|
|
|
|
a = orderstmtinplace(a)
|
|
|
|
|
a = walkstmt(a)
|
2016-03-07 22:54:46 -08:00
|
|
|
init.Append(a)
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
2016-04-23 22:59:01 -07:00
|
|
|
|
|
|
|
|
// make slice out of heap (6)
|
2016-04-21 11:55:33 -07:00
|
|
|
a = Nod(OAS, var_, Nod(OSLICE, vauto, nil))
|
2016-04-23 22:59:01 -07:00
|
|
|
|
|
|
|
|
a = typecheck(a, Etop)
|
|
|
|
|
a = orderstmtinplace(a)
|
|
|
|
|
a = walkstmt(a)
|
|
|
|
|
init.Append(a)
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
2016-05-16 13:56:15 -07:00
|
|
|
func maplit(ctxt int, n *Node, m *Node, init *Nodes) {
|
2015-02-13 14:40:36 -05:00
|
|
|
ctxt = 0
|
|
|
|
|
|
|
|
|
|
// make the map var
|
2015-02-23 16:07:24 -05:00
|
|
|
nerr := nerrors
|
2015-02-13 14:40:36 -05:00
|
|
|
|
2015-02-23 16:07:24 -05:00
|
|
|
a := Nod(OMAKE, nil, nil)
|
2016-05-29 11:16:13 -07:00
|
|
|
a.List.Set2(typenod(n.Type), Nodintconst(int64(len(n.List.Slice()))))
|
2016-05-16 13:56:15 -07:00
|
|
|
litas(m, a, init)
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
|
// count the initializers
|
2016-02-28 14:39:38 -08:00
|
|
|
b := 0
|
2016-03-08 15:10:26 -08:00
|
|
|
for _, r := range n.List.Slice() {
|
2015-02-13 14:40:36 -05:00
|
|
|
if r.Op != OKEY {
|
2015-08-30 23:10:03 +02:00
|
|
|
Fatalf("maplit: rhs not OKEY: %v", r)
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
2015-09-08 22:22:44 +02:00
|
|
|
index := r.Left
|
|
|
|
|
value := r.Right
|
2015-02-13 14:40:36 -05:00
|
|
|
|
2015-02-17 22:13:49 -05:00
|
|
|
if isliteral(index) && isliteral(value) {
|
2015-02-13 14:40:36 -05:00
|
|
|
b++
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if b != 0 {
|
2016-05-16 13:56:15 -07:00
|
|
|
// build types [count]Tindex and [count]Tvalue
|
|
|
|
|
tk := typArray(n.Type.Key(), int64(b))
|
|
|
|
|
tv := typArray(n.Type.Val(), int64(b))
|
2015-02-13 14:40:36 -05:00
|
|
|
|
2016-02-28 14:39:38 -08:00
|
|
|
// TODO(josharian): suppress alg generation for these types?
|
2016-05-16 13:56:15 -07:00
|
|
|
dowidth(tk)
|
|
|
|
|
dowidth(tv)
|
2015-02-13 14:40:36 -05:00
|
|
|
|
2016-05-16 13:56:15 -07:00
|
|
|
// make and initialize static arrays
|
|
|
|
|
vstatk := staticname(tk, ctxt)
|
|
|
|
|
vstatv := staticname(tv, ctxt)
|
2015-02-13 14:40:36 -05:00
|
|
|
|
2015-02-23 16:07:24 -05:00
|
|
|
b := int64(0)
|
2016-03-08 15:10:26 -08:00
|
|
|
for _, r := range n.List.Slice() {
|
2015-02-13 14:40:36 -05:00
|
|
|
if r.Op != OKEY {
|
2015-08-30 23:10:03 +02:00
|
|
|
Fatalf("maplit: rhs not OKEY: %v", r)
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
2015-09-08 22:22:44 +02:00
|
|
|
index := r.Left
|
|
|
|
|
value := r.Right
|
2015-02-13 14:40:36 -05:00
|
|
|
|
2015-02-17 22:13:49 -05:00
|
|
|
if isliteral(index) && isliteral(value) {
|
2016-05-16 13:56:15 -07:00
|
|
|
// build vstatk[b] = index
|
2015-06-29 16:30:19 -04:00
|
|
|
setlineno(index)
|
2016-05-16 13:56:15 -07:00
|
|
|
lhs := Nod(OINDEX, vstatk, Nodintconst(b))
|
|
|
|
|
as := Nod(OAS, lhs, index)
|
|
|
|
|
as = typecheck(as, Etop)
|
|
|
|
|
as = walkexpr(as, init)
|
2016-05-16 14:23:12 -07:00
|
|
|
as.IsStatic = true
|
2016-05-16 13:56:15 -07:00
|
|
|
init.Append(as)
|
|
|
|
|
|
|
|
|
|
// build vstatv[b] = value
|
2015-06-29 16:30:19 -04:00
|
|
|
setlineno(value)
|
2016-05-16 13:56:15 -07:00
|
|
|
lhs = Nod(OINDEX, vstatv, Nodintconst(b))
|
|
|
|
|
as = Nod(OAS, lhs, value)
|
|
|
|
|
as = typecheck(as, Etop)
|
|
|
|
|
as = walkexpr(as, init)
|
2016-05-16 14:23:12 -07:00
|
|
|
as.IsStatic = true
|
2016-05-16 13:56:15 -07:00
|
|
|
init.Append(as)
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
|
b++
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// loop adding structure elements to map
|
2016-05-16 13:56:15 -07:00
|
|
|
// for i = 0; i < len(vstatk); i++ {
|
|
|
|
|
// map[vstatk[i]] = vstatv[i]
|
2015-02-13 14:40:36 -05:00
|
|
|
// }
|
2016-05-16 13:56:15 -07:00
|
|
|
i := temp(Types[TINT])
|
|
|
|
|
rhs := Nod(OINDEX, vstatv, i)
|
|
|
|
|
rhs.Bounded = true
|
2015-02-13 14:40:36 -05:00
|
|
|
|
2016-05-16 13:56:15 -07:00
|
|
|
kidx := Nod(OINDEX, vstatk, i)
|
|
|
|
|
kidx.Bounded = true
|
|
|
|
|
lhs := Nod(OINDEX, m, kidx)
|
2015-02-13 14:40:36 -05:00
|
|
|
|
2016-05-16 13:56:15 -07:00
|
|
|
zero := Nod(OAS, i, Nodintconst(0))
|
|
|
|
|
cond := Nod(OLT, i, Nodintconst(tk.NumElem()))
|
|
|
|
|
incr := Nod(OAS, i, Nod(OADD, i, Nodintconst(1)))
|
|
|
|
|
body := Nod(OAS, lhs, rhs)
|
2015-02-13 14:40:36 -05:00
|
|
|
|
2016-05-16 13:56:15 -07:00
|
|
|
loop := Nod(OFOR, cond, incr)
|
|
|
|
|
loop.Nbody.Set1(body)
|
|
|
|
|
loop.Ninit.Set1(zero)
|
2015-02-13 14:40:36 -05:00
|
|
|
|
2016-05-16 13:56:15 -07:00
|
|
|
loop = typecheck(loop, Etop)
|
|
|
|
|
loop = walkstmt(loop)
|
|
|
|
|
init.Append(loop)
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// put in dynamic entries one-at-a-time
|
2016-02-28 14:39:38 -08:00
|
|
|
var key, val *Node
|
2016-03-08 15:10:26 -08:00
|
|
|
for _, r := range n.List.Slice() {
|
2015-02-13 14:40:36 -05:00
|
|
|
if r.Op != OKEY {
|
2015-08-30 23:10:03 +02:00
|
|
|
Fatalf("maplit: rhs not OKEY: %v", r)
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
2015-09-08 22:22:44 +02:00
|
|
|
index := r.Left
|
|
|
|
|
value := r.Right
|
2015-02-13 14:40:36 -05:00
|
|
|
|
2015-02-17 22:13:49 -05:00
|
|
|
if isliteral(index) && isliteral(value) {
|
2015-02-13 14:40:36 -05:00
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// build list of var[c] = expr.
|
|
|
|
|
// use temporary so that mapassign1 can have addressable key, val.
|
|
|
|
|
if key == nil {
|
2016-05-16 13:56:15 -07:00
|
|
|
key = temp(m.Type.Key())
|
|
|
|
|
val = temp(m.Type.Val())
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
2015-06-29 16:30:19 -04:00
|
|
|
setlineno(r.Left)
|
2015-02-13 14:40:36 -05:00
|
|
|
a = Nod(OAS, key, r.Left)
|
cmd/compile: reduce use of **Node parameters
Escape analysis has a hard time with tree-like
structures (see #13493 and #14858).
This is unlikely to change.
As a result, when invoking a function that accepts
a **Node parameter, we usually allocate a *Node
on the heap. This happens a whole lot.
This CL changes functions from taking a **Node
to acting more like append: It both modifies
the input and returns a replacement for it.
Because of the cascading nature of escape analysis,
in order to get the benefits, I had to modify
almost all such functions. The remaining functions
are in racewalk and the backend. I would be happy
to update them as well in a separate CL.
This CL was created by manually updating the
function signatures and the directly impacted
bits of code. The callsites were then automatically
updated using a bespoke script:
https://gist.github.com/josharian/046b1be7aceae244de39
For ease of reviewing and future understanding,
this CL is also broken down into four CLs,
mailed separately, which show the manual
and the automated changes separately.
They are CLs 20990, 20991, 20992, and 20993.
Passes toolstash -cmp.
name old time/op new time/op delta
Template 335ms ± 5% 324ms ± 5% -3.35% (p=0.000 n=23+24)
Unicode 176ms ± 9% 165ms ± 6% -6.12% (p=0.000 n=23+24)
GoTypes 1.10s ± 4% 1.07s ± 2% -2.77% (p=0.000 n=24+24)
Compiler 5.31s ± 3% 5.15s ± 3% -2.95% (p=0.000 n=24+24)
MakeBash 41.6s ± 1% 41.7s ± 2% ~ (p=0.586 n=23+23)
name old alloc/op new alloc/op delta
Template 63.3MB ± 0% 62.4MB ± 0% -1.36% (p=0.000 n=25+23)
Unicode 42.4MB ± 0% 41.6MB ± 0% -1.99% (p=0.000 n=24+25)
GoTypes 220MB ± 0% 217MB ± 0% -1.11% (p=0.000 n=25+25)
Compiler 994MB ± 0% 973MB ± 0% -2.08% (p=0.000 n=24+25)
name old allocs/op new allocs/op delta
Template 681k ± 0% 574k ± 0% -15.71% (p=0.000 n=24+25)
Unicode 518k ± 0% 413k ± 0% -20.34% (p=0.000 n=25+24)
GoTypes 2.08M ± 0% 1.78M ± 0% -14.62% (p=0.000 n=25+25)
Compiler 9.26M ± 0% 7.64M ± 0% -17.48% (p=0.000 n=25+25)
name old text-bytes new text-bytes delta
HelloSize 578k ± 0% 578k ± 0% ~ (all samples are equal)
CmdGoSize 6.46M ± 0% 6.46M ± 0% ~ (all samples are equal)
name old data-bytes new data-bytes delta
HelloSize 128k ± 0% 128k ± 0% ~ (all samples are equal)
CmdGoSize 281k ± 0% 281k ± 0% ~ (all samples are equal)
name old exe-bytes new exe-bytes delta
HelloSize 921k ± 0% 921k ± 0% ~ (all samples are equal)
CmdGoSize 9.86M ± 0% 9.86M ± 0% ~ (all samples are equal)
Change-Id: I277d95bd56d51c166ef7f560647aeaa092f3f475
Reviewed-on: https://go-review.googlesource.com/20959
Reviewed-by: Dave Cheney <dave@cheney.net>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
2016-03-20 08:03:31 -07:00
|
|
|
a = typecheck(a, Etop)
|
|
|
|
|
a = walkstmt(a)
|
2016-03-07 22:54:46 -08:00
|
|
|
init.Append(a)
|
2015-06-29 16:30:19 -04:00
|
|
|
setlineno(r.Right)
|
2015-02-13 14:40:36 -05:00
|
|
|
a = Nod(OAS, val, r.Right)
|
cmd/compile: reduce use of **Node parameters
Escape analysis has a hard time with tree-like
structures (see #13493 and #14858).
This is unlikely to change.
As a result, when invoking a function that accepts
a **Node parameter, we usually allocate a *Node
on the heap. This happens a whole lot.
This CL changes functions from taking a **Node
to acting more like append: It both modifies
the input and returns a replacement for it.
Because of the cascading nature of escape analysis,
in order to get the benefits, I had to modify
almost all such functions. The remaining functions
are in racewalk and the backend. I would be happy
to update them as well in a separate CL.
This CL was created by manually updating the
function signatures and the directly impacted
bits of code. The callsites were then automatically
updated using a bespoke script:
https://gist.github.com/josharian/046b1be7aceae244de39
For ease of reviewing and future understanding,
this CL is also broken down into four CLs,
mailed separately, which show the manual
and the automated changes separately.
They are CLs 20990, 20991, 20992, and 20993.
Passes toolstash -cmp.
name old time/op new time/op delta
Template 335ms ± 5% 324ms ± 5% -3.35% (p=0.000 n=23+24)
Unicode 176ms ± 9% 165ms ± 6% -6.12% (p=0.000 n=23+24)
GoTypes 1.10s ± 4% 1.07s ± 2% -2.77% (p=0.000 n=24+24)
Compiler 5.31s ± 3% 5.15s ± 3% -2.95% (p=0.000 n=24+24)
MakeBash 41.6s ± 1% 41.7s ± 2% ~ (p=0.586 n=23+23)
name old alloc/op new alloc/op delta
Template 63.3MB ± 0% 62.4MB ± 0% -1.36% (p=0.000 n=25+23)
Unicode 42.4MB ± 0% 41.6MB ± 0% -1.99% (p=0.000 n=24+25)
GoTypes 220MB ± 0% 217MB ± 0% -1.11% (p=0.000 n=25+25)
Compiler 994MB ± 0% 973MB ± 0% -2.08% (p=0.000 n=24+25)
name old allocs/op new allocs/op delta
Template 681k ± 0% 574k ± 0% -15.71% (p=0.000 n=24+25)
Unicode 518k ± 0% 413k ± 0% -20.34% (p=0.000 n=25+24)
GoTypes 2.08M ± 0% 1.78M ± 0% -14.62% (p=0.000 n=25+25)
Compiler 9.26M ± 0% 7.64M ± 0% -17.48% (p=0.000 n=25+25)
name old text-bytes new text-bytes delta
HelloSize 578k ± 0% 578k ± 0% ~ (all samples are equal)
CmdGoSize 6.46M ± 0% 6.46M ± 0% ~ (all samples are equal)
name old data-bytes new data-bytes delta
HelloSize 128k ± 0% 128k ± 0% ~ (all samples are equal)
CmdGoSize 281k ± 0% 281k ± 0% ~ (all samples are equal)
name old exe-bytes new exe-bytes delta
HelloSize 921k ± 0% 921k ± 0% ~ (all samples are equal)
CmdGoSize 9.86M ± 0% 9.86M ± 0% ~ (all samples are equal)
Change-Id: I277d95bd56d51c166ef7f560647aeaa092f3f475
Reviewed-on: https://go-review.googlesource.com/20959
Reviewed-by: Dave Cheney <dave@cheney.net>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
2016-03-20 08:03:31 -07:00
|
|
|
a = typecheck(a, Etop)
|
|
|
|
|
a = walkstmt(a)
|
2016-03-07 22:54:46 -08:00
|
|
|
init.Append(a)
|
2015-02-13 14:40:36 -05:00
|
|
|
|
2015-06-29 16:30:19 -04:00
|
|
|
setlineno(val)
|
2016-05-16 13:56:15 -07:00
|
|
|
a = Nod(OAS, Nod(OINDEX, m, key), val)
|
cmd/compile: reduce use of **Node parameters
Escape analysis has a hard time with tree-like
structures (see #13493 and #14858).
This is unlikely to change.
As a result, when invoking a function that accepts
a **Node parameter, we usually allocate a *Node
on the heap. This happens a whole lot.
This CL changes functions from taking a **Node
to acting more like append: It both modifies
the input and returns a replacement for it.
Because of the cascading nature of escape analysis,
in order to get the benefits, I had to modify
almost all such functions. The remaining functions
are in racewalk and the backend. I would be happy
to update them as well in a separate CL.
This CL was created by manually updating the
function signatures and the directly impacted
bits of code. The callsites were then automatically
updated using a bespoke script:
https://gist.github.com/josharian/046b1be7aceae244de39
For ease of reviewing and future understanding,
this CL is also broken down into four CLs,
mailed separately, which show the manual
and the automated changes separately.
They are CLs 20990, 20991, 20992, and 20993.
Passes toolstash -cmp.
name old time/op new time/op delta
Template 335ms ± 5% 324ms ± 5% -3.35% (p=0.000 n=23+24)
Unicode 176ms ± 9% 165ms ± 6% -6.12% (p=0.000 n=23+24)
GoTypes 1.10s ± 4% 1.07s ± 2% -2.77% (p=0.000 n=24+24)
Compiler 5.31s ± 3% 5.15s ± 3% -2.95% (p=0.000 n=24+24)
MakeBash 41.6s ± 1% 41.7s ± 2% ~ (p=0.586 n=23+23)
name old alloc/op new alloc/op delta
Template 63.3MB ± 0% 62.4MB ± 0% -1.36% (p=0.000 n=25+23)
Unicode 42.4MB ± 0% 41.6MB ± 0% -1.99% (p=0.000 n=24+25)
GoTypes 220MB ± 0% 217MB ± 0% -1.11% (p=0.000 n=25+25)
Compiler 994MB ± 0% 973MB ± 0% -2.08% (p=0.000 n=24+25)
name old allocs/op new allocs/op delta
Template 681k ± 0% 574k ± 0% -15.71% (p=0.000 n=24+25)
Unicode 518k ± 0% 413k ± 0% -20.34% (p=0.000 n=25+24)
GoTypes 2.08M ± 0% 1.78M ± 0% -14.62% (p=0.000 n=25+25)
Compiler 9.26M ± 0% 7.64M ± 0% -17.48% (p=0.000 n=25+25)
name old text-bytes new text-bytes delta
HelloSize 578k ± 0% 578k ± 0% ~ (all samples are equal)
CmdGoSize 6.46M ± 0% 6.46M ± 0% ~ (all samples are equal)
name old data-bytes new data-bytes delta
HelloSize 128k ± 0% 128k ± 0% ~ (all samples are equal)
CmdGoSize 281k ± 0% 281k ± 0% ~ (all samples are equal)
name old exe-bytes new exe-bytes delta
HelloSize 921k ± 0% 921k ± 0% ~ (all samples are equal)
CmdGoSize 9.86M ± 0% 9.86M ± 0% ~ (all samples are equal)
Change-Id: I277d95bd56d51c166ef7f560647aeaa092f3f475
Reviewed-on: https://go-review.googlesource.com/20959
Reviewed-by: Dave Cheney <dave@cheney.net>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
2016-03-20 08:03:31 -07:00
|
|
|
a = typecheck(a, Etop)
|
|
|
|
|
a = walkstmt(a)
|
2016-03-07 22:54:46 -08:00
|
|
|
init.Append(a)
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
|
if nerr != nerrors {
|
|
|
|
|
break
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if key != nil {
|
|
|
|
|
a = Nod(OVARKILL, key, nil)
|
cmd/compile: reduce use of **Node parameters
Escape analysis has a hard time with tree-like
structures (see #13493 and #14858).
This is unlikely to change.
As a result, when invoking a function that accepts
a **Node parameter, we usually allocate a *Node
on the heap. This happens a whole lot.
This CL changes functions from taking a **Node
to acting more like append: It both modifies
the input and returns a replacement for it.
Because of the cascading nature of escape analysis,
in order to get the benefits, I had to modify
almost all such functions. The remaining functions
are in racewalk and the backend. I would be happy
to update them as well in a separate CL.
This CL was created by manually updating the
function signatures and the directly impacted
bits of code. The callsites were then automatically
updated using a bespoke script:
https://gist.github.com/josharian/046b1be7aceae244de39
For ease of reviewing and future understanding,
this CL is also broken down into four CLs,
mailed separately, which show the manual
and the automated changes separately.
They are CLs 20990, 20991, 20992, and 20993.
Passes toolstash -cmp.
name old time/op new time/op delta
Template 335ms ± 5% 324ms ± 5% -3.35% (p=0.000 n=23+24)
Unicode 176ms ± 9% 165ms ± 6% -6.12% (p=0.000 n=23+24)
GoTypes 1.10s ± 4% 1.07s ± 2% -2.77% (p=0.000 n=24+24)
Compiler 5.31s ± 3% 5.15s ± 3% -2.95% (p=0.000 n=24+24)
MakeBash 41.6s ± 1% 41.7s ± 2% ~ (p=0.586 n=23+23)
name old alloc/op new alloc/op delta
Template 63.3MB ± 0% 62.4MB ± 0% -1.36% (p=0.000 n=25+23)
Unicode 42.4MB ± 0% 41.6MB ± 0% -1.99% (p=0.000 n=24+25)
GoTypes 220MB ± 0% 217MB ± 0% -1.11% (p=0.000 n=25+25)
Compiler 994MB ± 0% 973MB ± 0% -2.08% (p=0.000 n=24+25)
name old allocs/op new allocs/op delta
Template 681k ± 0% 574k ± 0% -15.71% (p=0.000 n=24+25)
Unicode 518k ± 0% 413k ± 0% -20.34% (p=0.000 n=25+24)
GoTypes 2.08M ± 0% 1.78M ± 0% -14.62% (p=0.000 n=25+25)
Compiler 9.26M ± 0% 7.64M ± 0% -17.48% (p=0.000 n=25+25)
name old text-bytes new text-bytes delta
HelloSize 578k ± 0% 578k ± 0% ~ (all samples are equal)
CmdGoSize 6.46M ± 0% 6.46M ± 0% ~ (all samples are equal)
name old data-bytes new data-bytes delta
HelloSize 128k ± 0% 128k ± 0% ~ (all samples are equal)
CmdGoSize 281k ± 0% 281k ± 0% ~ (all samples are equal)
name old exe-bytes new exe-bytes delta
HelloSize 921k ± 0% 921k ± 0% ~ (all samples are equal)
CmdGoSize 9.86M ± 0% 9.86M ± 0% ~ (all samples are equal)
Change-Id: I277d95bd56d51c166ef7f560647aeaa092f3f475
Reviewed-on: https://go-review.googlesource.com/20959
Reviewed-by: Dave Cheney <dave@cheney.net>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
2016-03-20 08:03:31 -07:00
|
|
|
a = typecheck(a, Etop)
|
2016-03-07 22:54:46 -08:00
|
|
|
init.Append(a)
|
2015-02-13 14:40:36 -05:00
|
|
|
a = Nod(OVARKILL, val, nil)
|
cmd/compile: reduce use of **Node parameters
Escape analysis has a hard time with tree-like
structures (see #13493 and #14858).
This is unlikely to change.
As a result, when invoking a function that accepts
a **Node parameter, we usually allocate a *Node
on the heap. This happens a whole lot.
This CL changes functions from taking a **Node
to acting more like append: It both modifies
the input and returns a replacement for it.
Because of the cascading nature of escape analysis,
in order to get the benefits, I had to modify
almost all such functions. The remaining functions
are in racewalk and the backend. I would be happy
to update them as well in a separate CL.
This CL was created by manually updating the
function signatures and the directly impacted
bits of code. The callsites were then automatically
updated using a bespoke script:
https://gist.github.com/josharian/046b1be7aceae244de39
For ease of reviewing and future understanding,
this CL is also broken down into four CLs,
mailed separately, which show the manual
and the automated changes separately.
They are CLs 20990, 20991, 20992, and 20993.
Passes toolstash -cmp.
name old time/op new time/op delta
Template 335ms ± 5% 324ms ± 5% -3.35% (p=0.000 n=23+24)
Unicode 176ms ± 9% 165ms ± 6% -6.12% (p=0.000 n=23+24)
GoTypes 1.10s ± 4% 1.07s ± 2% -2.77% (p=0.000 n=24+24)
Compiler 5.31s ± 3% 5.15s ± 3% -2.95% (p=0.000 n=24+24)
MakeBash 41.6s ± 1% 41.7s ± 2% ~ (p=0.586 n=23+23)
name old alloc/op new alloc/op delta
Template 63.3MB ± 0% 62.4MB ± 0% -1.36% (p=0.000 n=25+23)
Unicode 42.4MB ± 0% 41.6MB ± 0% -1.99% (p=0.000 n=24+25)
GoTypes 220MB ± 0% 217MB ± 0% -1.11% (p=0.000 n=25+25)
Compiler 994MB ± 0% 973MB ± 0% -2.08% (p=0.000 n=24+25)
name old allocs/op new allocs/op delta
Template 681k ± 0% 574k ± 0% -15.71% (p=0.000 n=24+25)
Unicode 518k ± 0% 413k ± 0% -20.34% (p=0.000 n=25+24)
GoTypes 2.08M ± 0% 1.78M ± 0% -14.62% (p=0.000 n=25+25)
Compiler 9.26M ± 0% 7.64M ± 0% -17.48% (p=0.000 n=25+25)
name old text-bytes new text-bytes delta
HelloSize 578k ± 0% 578k ± 0% ~ (all samples are equal)
CmdGoSize 6.46M ± 0% 6.46M ± 0% ~ (all samples are equal)
name old data-bytes new data-bytes delta
HelloSize 128k ± 0% 128k ± 0% ~ (all samples are equal)
CmdGoSize 281k ± 0% 281k ± 0% ~ (all samples are equal)
name old exe-bytes new exe-bytes delta
HelloSize 921k ± 0% 921k ± 0% ~ (all samples are equal)
CmdGoSize 9.86M ± 0% 9.86M ± 0% ~ (all samples are equal)
Change-Id: I277d95bd56d51c166ef7f560647aeaa092f3f475
Reviewed-on: https://go-review.googlesource.com/20959
Reviewed-by: Dave Cheney <dave@cheney.net>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
2016-03-20 08:03:31 -07:00
|
|
|
a = typecheck(a, Etop)
|
2016-03-07 22:54:46 -08:00
|
|
|
init.Append(a)
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2016-03-07 22:54:46 -08:00
|
|
|
func anylit(ctxt int, n *Node, var_ *Node, init *Nodes) {
|
2015-02-23 16:07:24 -05:00
|
|
|
t := n.Type
|
2015-02-13 14:40:36 -05:00
|
|
|
switch n.Op {
|
|
|
|
|
default:
|
2016-04-22 07:14:10 -07:00
|
|
|
Fatalf("anylit: not lit, op=%v node=%v", n.Op, n)
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
|
case OPTRLIT:
|
2016-03-30 15:09:25 -07:00
|
|
|
if !t.IsPtr() {
|
2015-08-30 23:10:03 +02:00
|
|
|
Fatalf("anylit: not ptr")
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
2015-02-23 16:07:24 -05:00
|
|
|
var r *Node
|
2015-02-13 14:40:36 -05:00
|
|
|
if n.Right != nil {
|
|
|
|
|
r = Nod(OADDR, n.Right, nil)
|
cmd/compile: reduce use of **Node parameters
Escape analysis has a hard time with tree-like
structures (see #13493 and #14858).
This is unlikely to change.
As a result, when invoking a function that accepts
a **Node parameter, we usually allocate a *Node
on the heap. This happens a whole lot.
This CL changes functions from taking a **Node
to acting more like append: It both modifies
the input and returns a replacement for it.
Because of the cascading nature of escape analysis,
in order to get the benefits, I had to modify
almost all such functions. The remaining functions
are in racewalk and the backend. I would be happy
to update them as well in a separate CL.
This CL was created by manually updating the
function signatures and the directly impacted
bits of code. The callsites were then automatically
updated using a bespoke script:
https://gist.github.com/josharian/046b1be7aceae244de39
For ease of reviewing and future understanding,
this CL is also broken down into four CLs,
mailed separately, which show the manual
and the automated changes separately.
They are CLs 20990, 20991, 20992, and 20993.
Passes toolstash -cmp.
name old time/op new time/op delta
Template 335ms ± 5% 324ms ± 5% -3.35% (p=0.000 n=23+24)
Unicode 176ms ± 9% 165ms ± 6% -6.12% (p=0.000 n=23+24)
GoTypes 1.10s ± 4% 1.07s ± 2% -2.77% (p=0.000 n=24+24)
Compiler 5.31s ± 3% 5.15s ± 3% -2.95% (p=0.000 n=24+24)
MakeBash 41.6s ± 1% 41.7s ± 2% ~ (p=0.586 n=23+23)
name old alloc/op new alloc/op delta
Template 63.3MB ± 0% 62.4MB ± 0% -1.36% (p=0.000 n=25+23)
Unicode 42.4MB ± 0% 41.6MB ± 0% -1.99% (p=0.000 n=24+25)
GoTypes 220MB ± 0% 217MB ± 0% -1.11% (p=0.000 n=25+25)
Compiler 994MB ± 0% 973MB ± 0% -2.08% (p=0.000 n=24+25)
name old allocs/op new allocs/op delta
Template 681k ± 0% 574k ± 0% -15.71% (p=0.000 n=24+25)
Unicode 518k ± 0% 413k ± 0% -20.34% (p=0.000 n=25+24)
GoTypes 2.08M ± 0% 1.78M ± 0% -14.62% (p=0.000 n=25+25)
Compiler 9.26M ± 0% 7.64M ± 0% -17.48% (p=0.000 n=25+25)
name old text-bytes new text-bytes delta
HelloSize 578k ± 0% 578k ± 0% ~ (all samples are equal)
CmdGoSize 6.46M ± 0% 6.46M ± 0% ~ (all samples are equal)
name old data-bytes new data-bytes delta
HelloSize 128k ± 0% 128k ± 0% ~ (all samples are equal)
CmdGoSize 281k ± 0% 281k ± 0% ~ (all samples are equal)
name old exe-bytes new exe-bytes delta
HelloSize 921k ± 0% 921k ± 0% ~ (all samples are equal)
CmdGoSize 9.86M ± 0% 9.86M ± 0% ~ (all samples are equal)
Change-Id: I277d95bd56d51c166ef7f560647aeaa092f3f475
Reviewed-on: https://go-review.googlesource.com/20959
Reviewed-by: Dave Cheney <dave@cheney.net>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
2016-03-20 08:03:31 -07:00
|
|
|
r = typecheck(r, Erv)
|
2015-02-13 14:40:36 -05:00
|
|
|
} else {
|
|
|
|
|
r = Nod(ONEW, nil, nil)
|
|
|
|
|
r.Typecheck = 1
|
|
|
|
|
r.Type = t
|
|
|
|
|
r.Esc = n.Esc
|
|
|
|
|
}
|
|
|
|
|
|
cmd/compile: reduce use of **Node parameters
Escape analysis has a hard time with tree-like
structures (see #13493 and #14858).
This is unlikely to change.
As a result, when invoking a function that accepts
a **Node parameter, we usually allocate a *Node
on the heap. This happens a whole lot.
This CL changes functions from taking a **Node
to acting more like append: It both modifies
the input and returns a replacement for it.
Because of the cascading nature of escape analysis,
in order to get the benefits, I had to modify
almost all such functions. The remaining functions
are in racewalk and the backend. I would be happy
to update them as well in a separate CL.
This CL was created by manually updating the
function signatures and the directly impacted
bits of code. The callsites were then automatically
updated using a bespoke script:
https://gist.github.com/josharian/046b1be7aceae244de39
For ease of reviewing and future understanding,
this CL is also broken down into four CLs,
mailed separately, which show the manual
and the automated changes separately.
They are CLs 20990, 20991, 20992, and 20993.
Passes toolstash -cmp.
name old time/op new time/op delta
Template 335ms ± 5% 324ms ± 5% -3.35% (p=0.000 n=23+24)
Unicode 176ms ± 9% 165ms ± 6% -6.12% (p=0.000 n=23+24)
GoTypes 1.10s ± 4% 1.07s ± 2% -2.77% (p=0.000 n=24+24)
Compiler 5.31s ± 3% 5.15s ± 3% -2.95% (p=0.000 n=24+24)
MakeBash 41.6s ± 1% 41.7s ± 2% ~ (p=0.586 n=23+23)
name old alloc/op new alloc/op delta
Template 63.3MB ± 0% 62.4MB ± 0% -1.36% (p=0.000 n=25+23)
Unicode 42.4MB ± 0% 41.6MB ± 0% -1.99% (p=0.000 n=24+25)
GoTypes 220MB ± 0% 217MB ± 0% -1.11% (p=0.000 n=25+25)
Compiler 994MB ± 0% 973MB ± 0% -2.08% (p=0.000 n=24+25)
name old allocs/op new allocs/op delta
Template 681k ± 0% 574k ± 0% -15.71% (p=0.000 n=24+25)
Unicode 518k ± 0% 413k ± 0% -20.34% (p=0.000 n=25+24)
GoTypes 2.08M ± 0% 1.78M ± 0% -14.62% (p=0.000 n=25+25)
Compiler 9.26M ± 0% 7.64M ± 0% -17.48% (p=0.000 n=25+25)
name old text-bytes new text-bytes delta
HelloSize 578k ± 0% 578k ± 0% ~ (all samples are equal)
CmdGoSize 6.46M ± 0% 6.46M ± 0% ~ (all samples are equal)
name old data-bytes new data-bytes delta
HelloSize 128k ± 0% 128k ± 0% ~ (all samples are equal)
CmdGoSize 281k ± 0% 281k ± 0% ~ (all samples are equal)
name old exe-bytes new exe-bytes delta
HelloSize 921k ± 0% 921k ± 0% ~ (all samples are equal)
CmdGoSize 9.86M ± 0% 9.86M ± 0% ~ (all samples are equal)
Change-Id: I277d95bd56d51c166ef7f560647aeaa092f3f475
Reviewed-on: https://go-review.googlesource.com/20959
Reviewed-by: Dave Cheney <dave@cheney.net>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
2016-03-20 08:03:31 -07:00
|
|
|
r = walkexpr(r, init)
|
2015-02-23 16:07:24 -05:00
|
|
|
a := Nod(OAS, var_, r)
|
2015-02-13 14:40:36 -05:00
|
|
|
|
cmd/compile: reduce use of **Node parameters
Escape analysis has a hard time with tree-like
structures (see #13493 and #14858).
This is unlikely to change.
As a result, when invoking a function that accepts
a **Node parameter, we usually allocate a *Node
on the heap. This happens a whole lot.
This CL changes functions from taking a **Node
to acting more like append: It both modifies
the input and returns a replacement for it.
Because of the cascading nature of escape analysis,
in order to get the benefits, I had to modify
almost all such functions. The remaining functions
are in racewalk and the backend. I would be happy
to update them as well in a separate CL.
This CL was created by manually updating the
function signatures and the directly impacted
bits of code. The callsites were then automatically
updated using a bespoke script:
https://gist.github.com/josharian/046b1be7aceae244de39
For ease of reviewing and future understanding,
this CL is also broken down into four CLs,
mailed separately, which show the manual
and the automated changes separately.
They are CLs 20990, 20991, 20992, and 20993.
Passes toolstash -cmp.
name old time/op new time/op delta
Template 335ms ± 5% 324ms ± 5% -3.35% (p=0.000 n=23+24)
Unicode 176ms ± 9% 165ms ± 6% -6.12% (p=0.000 n=23+24)
GoTypes 1.10s ± 4% 1.07s ± 2% -2.77% (p=0.000 n=24+24)
Compiler 5.31s ± 3% 5.15s ± 3% -2.95% (p=0.000 n=24+24)
MakeBash 41.6s ± 1% 41.7s ± 2% ~ (p=0.586 n=23+23)
name old alloc/op new alloc/op delta
Template 63.3MB ± 0% 62.4MB ± 0% -1.36% (p=0.000 n=25+23)
Unicode 42.4MB ± 0% 41.6MB ± 0% -1.99% (p=0.000 n=24+25)
GoTypes 220MB ± 0% 217MB ± 0% -1.11% (p=0.000 n=25+25)
Compiler 994MB ± 0% 973MB ± 0% -2.08% (p=0.000 n=24+25)
name old allocs/op new allocs/op delta
Template 681k ± 0% 574k ± 0% -15.71% (p=0.000 n=24+25)
Unicode 518k ± 0% 413k ± 0% -20.34% (p=0.000 n=25+24)
GoTypes 2.08M ± 0% 1.78M ± 0% -14.62% (p=0.000 n=25+25)
Compiler 9.26M ± 0% 7.64M ± 0% -17.48% (p=0.000 n=25+25)
name old text-bytes new text-bytes delta
HelloSize 578k ± 0% 578k ± 0% ~ (all samples are equal)
CmdGoSize 6.46M ± 0% 6.46M ± 0% ~ (all samples are equal)
name old data-bytes new data-bytes delta
HelloSize 128k ± 0% 128k ± 0% ~ (all samples are equal)
CmdGoSize 281k ± 0% 281k ± 0% ~ (all samples are equal)
name old exe-bytes new exe-bytes delta
HelloSize 921k ± 0% 921k ± 0% ~ (all samples are equal)
CmdGoSize 9.86M ± 0% 9.86M ± 0% ~ (all samples are equal)
Change-Id: I277d95bd56d51c166ef7f560647aeaa092f3f475
Reviewed-on: https://go-review.googlesource.com/20959
Reviewed-by: Dave Cheney <dave@cheney.net>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
2016-03-20 08:03:31 -07:00
|
|
|
a = typecheck(a, Etop)
|
2016-03-07 22:54:46 -08:00
|
|
|
init.Append(a)
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
|
var_ = Nod(OIND, var_, nil)
|
cmd/compile: reduce use of **Node parameters
Escape analysis has a hard time with tree-like
structures (see #13493 and #14858).
This is unlikely to change.
As a result, when invoking a function that accepts
a **Node parameter, we usually allocate a *Node
on the heap. This happens a whole lot.
This CL changes functions from taking a **Node
to acting more like append: It both modifies
the input and returns a replacement for it.
Because of the cascading nature of escape analysis,
in order to get the benefits, I had to modify
almost all such functions. The remaining functions
are in racewalk and the backend. I would be happy
to update them as well in a separate CL.
This CL was created by manually updating the
function signatures and the directly impacted
bits of code. The callsites were then automatically
updated using a bespoke script:
https://gist.github.com/josharian/046b1be7aceae244de39
For ease of reviewing and future understanding,
this CL is also broken down into four CLs,
mailed separately, which show the manual
and the automated changes separately.
They are CLs 20990, 20991, 20992, and 20993.
Passes toolstash -cmp.
name old time/op new time/op delta
Template 335ms ± 5% 324ms ± 5% -3.35% (p=0.000 n=23+24)
Unicode 176ms ± 9% 165ms ± 6% -6.12% (p=0.000 n=23+24)
GoTypes 1.10s ± 4% 1.07s ± 2% -2.77% (p=0.000 n=24+24)
Compiler 5.31s ± 3% 5.15s ± 3% -2.95% (p=0.000 n=24+24)
MakeBash 41.6s ± 1% 41.7s ± 2% ~ (p=0.586 n=23+23)
name old alloc/op new alloc/op delta
Template 63.3MB ± 0% 62.4MB ± 0% -1.36% (p=0.000 n=25+23)
Unicode 42.4MB ± 0% 41.6MB ± 0% -1.99% (p=0.000 n=24+25)
GoTypes 220MB ± 0% 217MB ± 0% -1.11% (p=0.000 n=25+25)
Compiler 994MB ± 0% 973MB ± 0% -2.08% (p=0.000 n=24+25)
name old allocs/op new allocs/op delta
Template 681k ± 0% 574k ± 0% -15.71% (p=0.000 n=24+25)
Unicode 518k ± 0% 413k ± 0% -20.34% (p=0.000 n=25+24)
GoTypes 2.08M ± 0% 1.78M ± 0% -14.62% (p=0.000 n=25+25)
Compiler 9.26M ± 0% 7.64M ± 0% -17.48% (p=0.000 n=25+25)
name old text-bytes new text-bytes delta
HelloSize 578k ± 0% 578k ± 0% ~ (all samples are equal)
CmdGoSize 6.46M ± 0% 6.46M ± 0% ~ (all samples are equal)
name old data-bytes new data-bytes delta
HelloSize 128k ± 0% 128k ± 0% ~ (all samples are equal)
CmdGoSize 281k ± 0% 281k ± 0% ~ (all samples are equal)
name old exe-bytes new exe-bytes delta
HelloSize 921k ± 0% 921k ± 0% ~ (all samples are equal)
CmdGoSize 9.86M ± 0% 9.86M ± 0% ~ (all samples are equal)
Change-Id: I277d95bd56d51c166ef7f560647aeaa092f3f475
Reviewed-on: https://go-review.googlesource.com/20959
Reviewed-by: Dave Cheney <dave@cheney.net>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
2016-03-20 08:03:31 -07:00
|
|
|
var_ = typecheck(var_, Erv|Easgn)
|
2015-02-13 14:40:36 -05:00
|
|
|
anylit(ctxt, n.Left, var_, init)
|
|
|
|
|
|
|
|
|
|
case OSTRUCTLIT:
|
2016-03-30 14:56:08 -07:00
|
|
|
if !t.IsStruct() {
|
2015-08-30 23:10:03 +02:00
|
|
|
Fatalf("anylit: not struct")
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
2016-03-14 14:03:57 -07:00
|
|
|
if var_.isSimpleName() && n.List.Len() > 4 {
|
2015-02-13 14:40:36 -05:00
|
|
|
if ctxt == 0 {
|
|
|
|
|
// lay out static data
|
2015-02-23 16:07:24 -05:00
|
|
|
vstat := staticname(t, ctxt)
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
|
structlit(ctxt, 1, n, vstat, init)
|
|
|
|
|
|
|
|
|
|
// copy static to var
|
2015-02-23 16:07:24 -05:00
|
|
|
a := Nod(OAS, var_, vstat)
|
2015-02-13 14:40:36 -05:00
|
|
|
|
cmd/compile: reduce use of **Node parameters
Escape analysis has a hard time with tree-like
structures (see #13493 and #14858).
This is unlikely to change.
As a result, when invoking a function that accepts
a **Node parameter, we usually allocate a *Node
on the heap. This happens a whole lot.
This CL changes functions from taking a **Node
to acting more like append: It both modifies
the input and returns a replacement for it.
Because of the cascading nature of escape analysis,
in order to get the benefits, I had to modify
almost all such functions. The remaining functions
are in racewalk and the backend. I would be happy
to update them as well in a separate CL.
This CL was created by manually updating the
function signatures and the directly impacted
bits of code. The callsites were then automatically
updated using a bespoke script:
https://gist.github.com/josharian/046b1be7aceae244de39
For ease of reviewing and future understanding,
this CL is also broken down into four CLs,
mailed separately, which show the manual
and the automated changes separately.
They are CLs 20990, 20991, 20992, and 20993.
Passes toolstash -cmp.
name old time/op new time/op delta
Template 335ms ± 5% 324ms ± 5% -3.35% (p=0.000 n=23+24)
Unicode 176ms ± 9% 165ms ± 6% -6.12% (p=0.000 n=23+24)
GoTypes 1.10s ± 4% 1.07s ± 2% -2.77% (p=0.000 n=24+24)
Compiler 5.31s ± 3% 5.15s ± 3% -2.95% (p=0.000 n=24+24)
MakeBash 41.6s ± 1% 41.7s ± 2% ~ (p=0.586 n=23+23)
name old alloc/op new alloc/op delta
Template 63.3MB ± 0% 62.4MB ± 0% -1.36% (p=0.000 n=25+23)
Unicode 42.4MB ± 0% 41.6MB ± 0% -1.99% (p=0.000 n=24+25)
GoTypes 220MB ± 0% 217MB ± 0% -1.11% (p=0.000 n=25+25)
Compiler 994MB ± 0% 973MB ± 0% -2.08% (p=0.000 n=24+25)
name old allocs/op new allocs/op delta
Template 681k ± 0% 574k ± 0% -15.71% (p=0.000 n=24+25)
Unicode 518k ± 0% 413k ± 0% -20.34% (p=0.000 n=25+24)
GoTypes 2.08M ± 0% 1.78M ± 0% -14.62% (p=0.000 n=25+25)
Compiler 9.26M ± 0% 7.64M ± 0% -17.48% (p=0.000 n=25+25)
name old text-bytes new text-bytes delta
HelloSize 578k ± 0% 578k ± 0% ~ (all samples are equal)
CmdGoSize 6.46M ± 0% 6.46M ± 0% ~ (all samples are equal)
name old data-bytes new data-bytes delta
HelloSize 128k ± 0% 128k ± 0% ~ (all samples are equal)
CmdGoSize 281k ± 0% 281k ± 0% ~ (all samples are equal)
name old exe-bytes new exe-bytes delta
HelloSize 921k ± 0% 921k ± 0% ~ (all samples are equal)
CmdGoSize 9.86M ± 0% 9.86M ± 0% ~ (all samples are equal)
Change-Id: I277d95bd56d51c166ef7f560647aeaa092f3f475
Reviewed-on: https://go-review.googlesource.com/20959
Reviewed-by: Dave Cheney <dave@cheney.net>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
2016-03-20 08:03:31 -07:00
|
|
|
a = typecheck(a, Etop)
|
|
|
|
|
a = walkexpr(a, init)
|
2016-03-07 22:54:46 -08:00
|
|
|
init.Append(a)
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
|
// add expressions to automatic
|
|
|
|
|
structlit(ctxt, 2, n, var_, init)
|
|
|
|
|
|
|
|
|
|
break
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
structlit(ctxt, 1, n, var_, init)
|
|
|
|
|
structlit(ctxt, 2, n, var_, init)
|
|
|
|
|
break
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// initialize of not completely specified
|
2016-03-17 13:26:08 -07:00
|
|
|
if var_.isSimpleName() || n.List.Len() < t.NumFields() {
|
2015-02-23 16:07:24 -05:00
|
|
|
a := Nod(OAS, var_, nil)
|
cmd/compile: reduce use of **Node parameters
Escape analysis has a hard time with tree-like
structures (see #13493 and #14858).
This is unlikely to change.
As a result, when invoking a function that accepts
a **Node parameter, we usually allocate a *Node
on the heap. This happens a whole lot.
This CL changes functions from taking a **Node
to acting more like append: It both modifies
the input and returns a replacement for it.
Because of the cascading nature of escape analysis,
in order to get the benefits, I had to modify
almost all such functions. The remaining functions
are in racewalk and the backend. I would be happy
to update them as well in a separate CL.
This CL was created by manually updating the
function signatures and the directly impacted
bits of code. The callsites were then automatically
updated using a bespoke script:
https://gist.github.com/josharian/046b1be7aceae244de39
For ease of reviewing and future understanding,
this CL is also broken down into four CLs,
mailed separately, which show the manual
and the automated changes separately.
They are CLs 20990, 20991, 20992, and 20993.
Passes toolstash -cmp.
name old time/op new time/op delta
Template 335ms ± 5% 324ms ± 5% -3.35% (p=0.000 n=23+24)
Unicode 176ms ± 9% 165ms ± 6% -6.12% (p=0.000 n=23+24)
GoTypes 1.10s ± 4% 1.07s ± 2% -2.77% (p=0.000 n=24+24)
Compiler 5.31s ± 3% 5.15s ± 3% -2.95% (p=0.000 n=24+24)
MakeBash 41.6s ± 1% 41.7s ± 2% ~ (p=0.586 n=23+23)
name old alloc/op new alloc/op delta
Template 63.3MB ± 0% 62.4MB ± 0% -1.36% (p=0.000 n=25+23)
Unicode 42.4MB ± 0% 41.6MB ± 0% -1.99% (p=0.000 n=24+25)
GoTypes 220MB ± 0% 217MB ± 0% -1.11% (p=0.000 n=25+25)
Compiler 994MB ± 0% 973MB ± 0% -2.08% (p=0.000 n=24+25)
name old allocs/op new allocs/op delta
Template 681k ± 0% 574k ± 0% -15.71% (p=0.000 n=24+25)
Unicode 518k ± 0% 413k ± 0% -20.34% (p=0.000 n=25+24)
GoTypes 2.08M ± 0% 1.78M ± 0% -14.62% (p=0.000 n=25+25)
Compiler 9.26M ± 0% 7.64M ± 0% -17.48% (p=0.000 n=25+25)
name old text-bytes new text-bytes delta
HelloSize 578k ± 0% 578k ± 0% ~ (all samples are equal)
CmdGoSize 6.46M ± 0% 6.46M ± 0% ~ (all samples are equal)
name old data-bytes new data-bytes delta
HelloSize 128k ± 0% 128k ± 0% ~ (all samples are equal)
CmdGoSize 281k ± 0% 281k ± 0% ~ (all samples are equal)
name old exe-bytes new exe-bytes delta
HelloSize 921k ± 0% 921k ± 0% ~ (all samples are equal)
CmdGoSize 9.86M ± 0% 9.86M ± 0% ~ (all samples are equal)
Change-Id: I277d95bd56d51c166ef7f560647aeaa092f3f475
Reviewed-on: https://go-review.googlesource.com/20959
Reviewed-by: Dave Cheney <dave@cheney.net>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
2016-03-20 08:03:31 -07:00
|
|
|
a = typecheck(a, Etop)
|
|
|
|
|
a = walkexpr(a, init)
|
2016-03-07 22:54:46 -08:00
|
|
|
init.Append(a)
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
structlit(ctxt, 3, n, var_, init)
|
|
|
|
|
|
|
|
|
|
case OARRAYLIT:
|
2016-03-29 09:14:19 -07:00
|
|
|
if t.IsSlice() {
|
2015-02-13 14:40:36 -05:00
|
|
|
slicelit(ctxt, n, var_, init)
|
|
|
|
|
break
|
|
|
|
|
}
|
2016-04-18 14:02:08 -07:00
|
|
|
if !t.IsArray() {
|
|
|
|
|
Fatalf("anylit: not array")
|
|
|
|
|
}
|
2015-02-13 14:40:36 -05:00
|
|
|
|
2016-03-14 14:03:57 -07:00
|
|
|
if var_.isSimpleName() && n.List.Len() > 4 {
|
2015-02-13 14:40:36 -05:00
|
|
|
if ctxt == 0 {
|
|
|
|
|
// lay out static data
|
2015-02-23 16:07:24 -05:00
|
|
|
vstat := staticname(t, ctxt)
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
|
arraylit(1, 1, n, vstat, init)
|
|
|
|
|
|
|
|
|
|
// copy static to automatic
|
2015-02-23 16:07:24 -05:00
|
|
|
a := Nod(OAS, var_, vstat)
|
2015-02-13 14:40:36 -05:00
|
|
|
|
cmd/compile: reduce use of **Node parameters
Escape analysis has a hard time with tree-like
structures (see #13493 and #14858).
This is unlikely to change.
As a result, when invoking a function that accepts
a **Node parameter, we usually allocate a *Node
on the heap. This happens a whole lot.
This CL changes functions from taking a **Node
to acting more like append: It both modifies
the input and returns a replacement for it.
Because of the cascading nature of escape analysis,
in order to get the benefits, I had to modify
almost all such functions. The remaining functions
are in racewalk and the backend. I would be happy
to update them as well in a separate CL.
This CL was created by manually updating the
function signatures and the directly impacted
bits of code. The callsites were then automatically
updated using a bespoke script:
https://gist.github.com/josharian/046b1be7aceae244de39
For ease of reviewing and future understanding,
this CL is also broken down into four CLs,
mailed separately, which show the manual
and the automated changes separately.
They are CLs 20990, 20991, 20992, and 20993.
Passes toolstash -cmp.
name old time/op new time/op delta
Template 335ms ± 5% 324ms ± 5% -3.35% (p=0.000 n=23+24)
Unicode 176ms ± 9% 165ms ± 6% -6.12% (p=0.000 n=23+24)
GoTypes 1.10s ± 4% 1.07s ± 2% -2.77% (p=0.000 n=24+24)
Compiler 5.31s ± 3% 5.15s ± 3% -2.95% (p=0.000 n=24+24)
MakeBash 41.6s ± 1% 41.7s ± 2% ~ (p=0.586 n=23+23)
name old alloc/op new alloc/op delta
Template 63.3MB ± 0% 62.4MB ± 0% -1.36% (p=0.000 n=25+23)
Unicode 42.4MB ± 0% 41.6MB ± 0% -1.99% (p=0.000 n=24+25)
GoTypes 220MB ± 0% 217MB ± 0% -1.11% (p=0.000 n=25+25)
Compiler 994MB ± 0% 973MB ± 0% -2.08% (p=0.000 n=24+25)
name old allocs/op new allocs/op delta
Template 681k ± 0% 574k ± 0% -15.71% (p=0.000 n=24+25)
Unicode 518k ± 0% 413k ± 0% -20.34% (p=0.000 n=25+24)
GoTypes 2.08M ± 0% 1.78M ± 0% -14.62% (p=0.000 n=25+25)
Compiler 9.26M ± 0% 7.64M ± 0% -17.48% (p=0.000 n=25+25)
name old text-bytes new text-bytes delta
HelloSize 578k ± 0% 578k ± 0% ~ (all samples are equal)
CmdGoSize 6.46M ± 0% 6.46M ± 0% ~ (all samples are equal)
name old data-bytes new data-bytes delta
HelloSize 128k ± 0% 128k ± 0% ~ (all samples are equal)
CmdGoSize 281k ± 0% 281k ± 0% ~ (all samples are equal)
name old exe-bytes new exe-bytes delta
HelloSize 921k ± 0% 921k ± 0% ~ (all samples are equal)
CmdGoSize 9.86M ± 0% 9.86M ± 0% ~ (all samples are equal)
Change-Id: I277d95bd56d51c166ef7f560647aeaa092f3f475
Reviewed-on: https://go-review.googlesource.com/20959
Reviewed-by: Dave Cheney <dave@cheney.net>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
2016-03-20 08:03:31 -07:00
|
|
|
a = typecheck(a, Etop)
|
|
|
|
|
a = walkexpr(a, init)
|
2016-03-07 22:54:46 -08:00
|
|
|
init.Append(a)
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
|
// add expressions to automatic
|
|
|
|
|
arraylit(ctxt, 2, n, var_, init)
|
|
|
|
|
|
|
|
|
|
break
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
arraylit(ctxt, 1, n, var_, init)
|
|
|
|
|
arraylit(ctxt, 2, n, var_, init)
|
|
|
|
|
break
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// initialize of not completely specified
|
2016-03-31 14:46:04 -07:00
|
|
|
if var_.isSimpleName() || int64(n.List.Len()) < t.NumElem() {
|
2015-02-23 16:07:24 -05:00
|
|
|
a := Nod(OAS, var_, nil)
|
cmd/compile: reduce use of **Node parameters
Escape analysis has a hard time with tree-like
structures (see #13493 and #14858).
This is unlikely to change.
As a result, when invoking a function that accepts
a **Node parameter, we usually allocate a *Node
on the heap. This happens a whole lot.
This CL changes functions from taking a **Node
to acting more like append: It both modifies
the input and returns a replacement for it.
Because of the cascading nature of escape analysis,
in order to get the benefits, I had to modify
almost all such functions. The remaining functions
are in racewalk and the backend. I would be happy
to update them as well in a separate CL.
This CL was created by manually updating the
function signatures and the directly impacted
bits of code. The callsites were then automatically
updated using a bespoke script:
https://gist.github.com/josharian/046b1be7aceae244de39
For ease of reviewing and future understanding,
this CL is also broken down into four CLs,
mailed separately, which show the manual
and the automated changes separately.
They are CLs 20990, 20991, 20992, and 20993.
Passes toolstash -cmp.
name old time/op new time/op delta
Template 335ms ± 5% 324ms ± 5% -3.35% (p=0.000 n=23+24)
Unicode 176ms ± 9% 165ms ± 6% -6.12% (p=0.000 n=23+24)
GoTypes 1.10s ± 4% 1.07s ± 2% -2.77% (p=0.000 n=24+24)
Compiler 5.31s ± 3% 5.15s ± 3% -2.95% (p=0.000 n=24+24)
MakeBash 41.6s ± 1% 41.7s ± 2% ~ (p=0.586 n=23+23)
name old alloc/op new alloc/op delta
Template 63.3MB ± 0% 62.4MB ± 0% -1.36% (p=0.000 n=25+23)
Unicode 42.4MB ± 0% 41.6MB ± 0% -1.99% (p=0.000 n=24+25)
GoTypes 220MB ± 0% 217MB ± 0% -1.11% (p=0.000 n=25+25)
Compiler 994MB ± 0% 973MB ± 0% -2.08% (p=0.000 n=24+25)
name old allocs/op new allocs/op delta
Template 681k ± 0% 574k ± 0% -15.71% (p=0.000 n=24+25)
Unicode 518k ± 0% 413k ± 0% -20.34% (p=0.000 n=25+24)
GoTypes 2.08M ± 0% 1.78M ± 0% -14.62% (p=0.000 n=25+25)
Compiler 9.26M ± 0% 7.64M ± 0% -17.48% (p=0.000 n=25+25)
name old text-bytes new text-bytes delta
HelloSize 578k ± 0% 578k ± 0% ~ (all samples are equal)
CmdGoSize 6.46M ± 0% 6.46M ± 0% ~ (all samples are equal)
name old data-bytes new data-bytes delta
HelloSize 128k ± 0% 128k ± 0% ~ (all samples are equal)
CmdGoSize 281k ± 0% 281k ± 0% ~ (all samples are equal)
name old exe-bytes new exe-bytes delta
HelloSize 921k ± 0% 921k ± 0% ~ (all samples are equal)
CmdGoSize 9.86M ± 0% 9.86M ± 0% ~ (all samples are equal)
Change-Id: I277d95bd56d51c166ef7f560647aeaa092f3f475
Reviewed-on: https://go-review.googlesource.com/20959
Reviewed-by: Dave Cheney <dave@cheney.net>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
2016-03-20 08:03:31 -07:00
|
|
|
a = typecheck(a, Etop)
|
|
|
|
|
a = walkexpr(a, init)
|
2016-03-07 22:54:46 -08:00
|
|
|
init.Append(a)
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
arraylit(ctxt, 3, n, var_, init)
|
|
|
|
|
|
|
|
|
|
case OMAPLIT:
|
2016-03-30 14:56:08 -07:00
|
|
|
if !t.IsMap() {
|
2015-08-30 23:10:03 +02:00
|
|
|
Fatalf("anylit: not map")
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
maplit(ctxt, n, var_, init)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2016-03-07 22:54:46 -08:00
|
|
|
func oaslit(n *Node, init *Nodes) bool {
|
2015-02-13 14:40:36 -05:00
|
|
|
if n.Left == nil || n.Right == nil {
|
2015-03-02 12:35:15 -05:00
|
|
|
// not a special composit literal assignment
|
|
|
|
|
return false
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
if n.Left.Type == nil || n.Right.Type == nil {
|
2015-03-02 12:35:15 -05:00
|
|
|
// not a special composit literal assignment
|
|
|
|
|
return false
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
2016-03-14 14:03:57 -07:00
|
|
|
if !n.Left.isSimpleName() {
|
2015-03-02 12:35:15 -05:00
|
|
|
// not a special composit literal assignment
|
|
|
|
|
return false
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
if !Eqtype(n.Left.Type, n.Right.Type) {
|
2015-03-02 12:35:15 -05:00
|
|
|
// not a special composit literal assignment
|
|
|
|
|
return false
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// context is init() function.
|
|
|
|
|
// implies generated data executed
|
|
|
|
|
// exactly once and not subject to races.
|
2015-03-02 12:35:15 -05:00
|
|
|
ctxt := 0
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
|
// if(n->dodata == 1)
|
|
|
|
|
// ctxt = 1;
|
|
|
|
|
|
|
|
|
|
switch n.Right.Op {
|
|
|
|
|
default:
|
2015-03-02 12:35:15 -05:00
|
|
|
// not a special composit literal assignment
|
|
|
|
|
return false
|
2015-02-13 14:40:36 -05:00
|
|
|
|
2015-04-01 09:38:44 -07:00
|
|
|
case OSTRUCTLIT, OARRAYLIT, OMAPLIT:
|
2015-02-17 22:13:49 -05:00
|
|
|
if vmatch1(n.Left, n.Right) {
|
2015-03-02 12:35:15 -05:00
|
|
|
// not a special composit literal assignment
|
|
|
|
|
return false
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
anylit(ctxt, n.Right, n.Left, init)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
n.Op = OEMPTY
|
2015-05-26 21:30:20 -04:00
|
|
|
n.Right = nil
|
2015-02-17 22:13:49 -05:00
|
|
|
return true
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func getlit(lit *Node) int {
|
2015-02-17 22:13:49 -05:00
|
|
|
if Smallintconst(lit) {
|
2016-04-01 14:51:02 -07:00
|
|
|
return int(lit.Int64())
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
return -1
|
|
|
|
|
}
|
|
|
|
|
|
2015-07-28 10:56:39 -07:00
|
|
|
// stataddr sets nam to the static address of n and reports whether it succeeeded.
|
2015-02-17 22:13:49 -05:00
|
|
|
func stataddr(nam *Node, n *Node) bool {
|
2015-02-13 14:40:36 -05:00
|
|
|
if n == nil {
|
2015-03-02 12:35:15 -05:00
|
|
|
return false
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
switch n.Op {
|
|
|
|
|
case ONAME:
|
|
|
|
|
*nam = *n
|
2015-04-02 19:58:37 -07:00
|
|
|
return n.Addable
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
|
case ODOT:
|
2015-02-17 22:13:49 -05:00
|
|
|
if !stataddr(nam, n.Left) {
|
2015-02-13 14:40:36 -05:00
|
|
|
break
|
|
|
|
|
}
|
|
|
|
|
nam.Xoffset += n.Xoffset
|
|
|
|
|
nam.Type = n.Type
|
2015-02-17 22:13:49 -05:00
|
|
|
return true
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
|
case OINDEX:
|
2016-03-29 09:14:19 -07:00
|
|
|
if n.Left.Type.IsSlice() {
|
2015-02-13 14:40:36 -05:00
|
|
|
break
|
|
|
|
|
}
|
2015-02-17 22:13:49 -05:00
|
|
|
if !stataddr(nam, n.Left) {
|
2015-02-13 14:40:36 -05:00
|
|
|
break
|
|
|
|
|
}
|
2015-02-23 16:07:24 -05:00
|
|
|
l := getlit(n.Right)
|
2015-02-13 14:40:36 -05:00
|
|
|
if l < 0 {
|
|
|
|
|
break
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Check for overflow.
|
|
|
|
|
if n.Type.Width != 0 && Thearch.MAXWIDTH/n.Type.Width <= int64(l) {
|
|
|
|
|
break
|
|
|
|
|
}
|
|
|
|
|
nam.Xoffset += int64(l) * n.Type.Width
|
|
|
|
|
nam.Type = n.Type
|
2015-02-17 22:13:49 -05:00
|
|
|
return true
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
2015-02-17 22:13:49 -05:00
|
|
|
return false
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func initplan(n *Node) {
|
2015-05-22 01:16:52 -04:00
|
|
|
if initplans[n] != nil {
|
2015-02-13 14:40:36 -05:00
|
|
|
return
|
|
|
|
|
}
|
2015-02-23 16:07:24 -05:00
|
|
|
p := new(InitPlan)
|
2015-05-22 01:16:52 -04:00
|
|
|
initplans[n] = p
|
2015-02-13 14:40:36 -05:00
|
|
|
switch n.Op {
|
|
|
|
|
default:
|
2015-08-30 23:10:03 +02:00
|
|
|
Fatalf("initplan")
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
|
case OARRAYLIT:
|
2016-03-08 15:10:26 -08:00
|
|
|
for _, a := range n.List.Slice() {
|
2015-02-17 22:13:49 -05:00
|
|
|
if a.Op != OKEY || !Smallintconst(a.Left) {
|
2015-08-30 23:10:03 +02:00
|
|
|
Fatalf("initplan arraylit")
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
2016-04-01 14:51:02 -07:00
|
|
|
addvalue(p, n.Type.Elem().Width*a.Left.Int64(), a.Right)
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
case OSTRUCTLIT:
|
2016-03-08 15:10:26 -08:00
|
|
|
for _, a := range n.List.Slice() {
|
2016-03-14 00:24:43 -07:00
|
|
|
if a.Op != OKEY || a.Left.Type != structkey {
|
2015-08-30 23:10:03 +02:00
|
|
|
Fatalf("initplan structlit")
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
2016-03-14 00:24:43 -07:00
|
|
|
addvalue(p, a.Left.Xoffset, a.Right)
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
case OMAPLIT:
|
2016-03-08 15:10:26 -08:00
|
|
|
for _, a := range n.List.Slice() {
|
2015-02-13 14:40:36 -05:00
|
|
|
if a.Op != OKEY {
|
2015-08-30 23:10:03 +02:00
|
|
|
Fatalf("initplan maplit")
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
2016-03-13 17:48:17 -07:00
|
|
|
addvalue(p, -1, a.Right)
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2016-03-13 17:48:17 -07:00
|
|
|
func addvalue(p *InitPlan, xoffset int64, n *Node) {
|
2015-02-13 14:40:36 -05:00
|
|
|
// special case: zero can be dropped entirely
|
2015-02-17 22:13:49 -05:00
|
|
|
if iszero(n) {
|
2015-02-13 14:40:36 -05:00
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// special case: inline struct and array (not slice) literals
|
2015-02-17 22:13:49 -05:00
|
|
|
if isvaluelit(n) {
|
2015-02-13 14:40:36 -05:00
|
|
|
initplan(n)
|
2015-05-22 01:16:52 -04:00
|
|
|
q := initplans[n]
|
2015-09-08 22:22:44 +02:00
|
|
|
for _, qe := range q.E {
|
2016-03-13 17:48:17 -07:00
|
|
|
// qe is a copy; we are not modifying entries in q.E
|
|
|
|
|
qe.Xoffset += xoffset
|
|
|
|
|
p.E = append(p.E, qe)
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// add to plan
|
2016-03-13 17:48:17 -07:00
|
|
|
p.E = append(p.E, InitEntry{Xoffset: xoffset, Expr: n})
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
2015-02-17 22:13:49 -05:00
|
|
|
func iszero(n *Node) bool {
|
2015-02-13 14:40:36 -05:00
|
|
|
switch n.Op {
|
|
|
|
|
case OLITERAL:
|
2016-04-22 12:27:29 -07:00
|
|
|
switch u := n.Val().U.(type) {
|
2015-02-13 14:40:36 -05:00
|
|
|
default:
|
|
|
|
|
Dump("unexpected literal", n)
|
2015-08-30 23:10:03 +02:00
|
|
|
Fatalf("iszero")
|
2016-04-22 12:27:29 -07:00
|
|
|
case *NilVal:
|
2015-02-17 22:13:49 -05:00
|
|
|
return true
|
2016-04-22 12:27:29 -07:00
|
|
|
case string:
|
|
|
|
|
return u == ""
|
|
|
|
|
case bool:
|
|
|
|
|
return !u
|
|
|
|
|
case *Mpint:
|
|
|
|
|
return u.CmpInt64(0) == 0
|
|
|
|
|
case *Mpflt:
|
|
|
|
|
return u.CmpFloat64(0) == 0
|
|
|
|
|
case *Mpcplx:
|
|
|
|
|
return u.Real.CmpFloat64(0) == 0 && u.Imag.CmpFloat64(0) == 0
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
case OARRAYLIT:
|
2016-03-30 14:45:47 -07:00
|
|
|
if n.Type.IsSlice() {
|
2015-02-13 14:40:36 -05:00
|
|
|
break
|
|
|
|
|
}
|
|
|
|
|
fallthrough
|
|
|
|
|
case OSTRUCTLIT:
|
2016-03-08 15:10:26 -08:00
|
|
|
for _, n1 := range n.List.Slice() {
|
|
|
|
|
if !iszero(n1.Right) {
|
2015-02-17 22:13:49 -05:00
|
|
|
return false
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
}
|
2015-02-17 22:13:49 -05:00
|
|
|
return true
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
2015-02-17 22:13:49 -05:00
|
|
|
return false
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
2015-02-17 22:13:49 -05:00
|
|
|
func isvaluelit(n *Node) bool {
|
2016-03-30 14:45:47 -07:00
|
|
|
return (n.Op == OARRAYLIT && n.Type.IsArray()) || n.Op == OSTRUCTLIT
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
2015-07-28 10:56:39 -07:00
|
|
|
// gen_as_init attempts to emit static data for n and reports whether it succeeded.
|
|
|
|
|
// If reportOnly is true, it does not emit static data and does not modify the AST.
|
|
|
|
|
func gen_as_init(n *Node, reportOnly bool) bool {
|
2016-03-14 14:03:57 -07:00
|
|
|
success := genAsInitNoCheck(n, reportOnly)
|
2016-05-16 14:23:12 -07:00
|
|
|
if !success && n.IsStatic {
|
2016-03-14 14:03:57 -07:00
|
|
|
Dump("\ngen_as_init", n)
|
2016-05-16 14:23:12 -07:00
|
|
|
Fatalf("gen_as_init couldn't generate static data")
|
2016-03-14 14:03:57 -07:00
|
|
|
}
|
|
|
|
|
return success
|
|
|
|
|
}
|
2015-02-13 14:40:36 -05:00
|
|
|
|
2016-03-14 14:03:57 -07:00
|
|
|
func genAsInitNoCheck(n *Node, reportOnly bool) bool {
|
2016-05-16 14:23:12 -07:00
|
|
|
if !n.IsStatic {
|
2016-03-14 14:03:57 -07:00
|
|
|
return false
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
2016-03-14 14:03:57 -07:00
|
|
|
nr := n.Right
|
|
|
|
|
nl := n.Left
|
2015-02-13 14:40:36 -05:00
|
|
|
if nr == nil {
|
2015-02-23 16:07:24 -05:00
|
|
|
var nam Node
|
2016-03-14 14:03:57 -07:00
|
|
|
return stataddr(&nam, nl) && nam.Class == PEXTERN
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if nr.Type == nil || !Eqtype(nl.Type, nr.Type) {
|
2016-03-14 14:03:57 -07:00
|
|
|
return false
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
2016-03-14 14:03:57 -07:00
|
|
|
var nam Node
|
|
|
|
|
if !stataddr(&nam, nl) || nam.Class != PEXTERN {
|
|
|
|
|
return false
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
switch nr.Op {
|
|
|
|
|
default:
|
2016-03-14 14:03:57 -07:00
|
|
|
return false
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
|
case OCONVNOP:
|
|
|
|
|
nr = nr.Left
|
|
|
|
|
if nr == nil || nr.Op != OSLICEARR {
|
2016-03-14 14:03:57 -07:00
|
|
|
return false
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
fallthrough
|
|
|
|
|
|
|
|
|
|
case OSLICEARR:
|
2016-04-21 11:55:33 -07:00
|
|
|
low, high, _ := nr.SliceBounds()
|
|
|
|
|
if low != nil || high != nil {
|
2016-03-14 14:03:57 -07:00
|
|
|
return false
|
|
|
|
|
}
|
|
|
|
|
nr = nr.Left
|
|
|
|
|
if nr == nil || nr.Op != OADDR {
|
|
|
|
|
return false
|
|
|
|
|
}
|
|
|
|
|
ptr := nr
|
|
|
|
|
nr = nr.Left
|
|
|
|
|
if nr == nil || nr.Op != ONAME {
|
|
|
|
|
return false
|
|
|
|
|
}
|
2015-03-02 12:35:15 -05:00
|
|
|
|
2016-03-14 14:03:57 -07:00
|
|
|
// nr is the array being converted to a slice
|
2016-04-18 14:02:08 -07:00
|
|
|
if nr.Type == nil || !nr.Type.IsArray() {
|
2016-03-14 14:03:57 -07:00
|
|
|
return false
|
|
|
|
|
}
|
2015-03-02 12:35:15 -05:00
|
|
|
|
2016-03-14 14:03:57 -07:00
|
|
|
if !reportOnly {
|
|
|
|
|
nam.Xoffset += int64(Array_array)
|
|
|
|
|
gdata(&nam, ptr, Widthptr)
|
2015-03-02 12:35:15 -05:00
|
|
|
|
2016-03-14 14:03:57 -07:00
|
|
|
nam.Xoffset += int64(Array_nel) - int64(Array_array)
|
|
|
|
|
var nod1 Node
|
2016-03-31 14:46:04 -07:00
|
|
|
Nodconst(&nod1, Types[TINT], nr.Type.NumElem())
|
2016-03-14 14:03:57 -07:00
|
|
|
gdata(&nam, &nod1, Widthint)
|
2015-03-02 12:35:15 -05:00
|
|
|
|
2016-03-14 14:03:57 -07:00
|
|
|
nam.Xoffset += int64(Array_cap) - int64(Array_nel)
|
|
|
|
|
gdata(&nam, &nod1, Widthint)
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
2016-03-14 14:03:57 -07:00
|
|
|
return true
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
|
case OLITERAL:
|
|
|
|
|
break
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
switch nr.Type.Etype {
|
|
|
|
|
default:
|
2016-03-14 14:03:57 -07:00
|
|
|
return false
|
2015-02-13 14:40:36 -05:00
|
|
|
|
2016-03-13 21:57:31 -07:00
|
|
|
case TBOOL, TINT8, TUINT8, TINT16, TUINT16,
|
|
|
|
|
TINT32, TUINT32, TINT64, TUINT64,
|
2016-07-08 15:59:00 -07:00
|
|
|
TINT, TUINT, TUINTPTR, TUNSAFEPTR,
|
2016-03-13 21:57:31 -07:00
|
|
|
TPTR32, TPTR64,
|
|
|
|
|
TFLOAT32, TFLOAT64:
|
2015-07-28 10:56:39 -07:00
|
|
|
if !reportOnly {
|
|
|
|
|
gdata(&nam, nr, int(nr.Type.Width))
|
|
|
|
|
}
|
2015-02-13 14:40:36 -05:00
|
|
|
|
2015-04-01 09:38:44 -07:00
|
|
|
case TCOMPLEX64, TCOMPLEX128:
|
2015-07-28 10:56:39 -07:00
|
|
|
if !reportOnly {
|
|
|
|
|
gdatacomplex(&nam, nr.Val().U.(*Mpcplx))
|
|
|
|
|
}
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
|
case TSTRING:
|
2015-07-28 10:56:39 -07:00
|
|
|
if !reportOnly {
|
|
|
|
|
gdatastring(&nam, nr.Val().U.(string))
|
|
|
|
|
}
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
2015-02-17 22:13:49 -05:00
|
|
|
return true
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|