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
|
|
|
|
|
cmd/compile: factor out Pkg, Sym, and Type into package types
- created new package cmd/compile/internal/types
- moved Pkg, Sym, Type to new package
- to break cycles, for now we need the (ugly) types/utils.go
file which contains a handful of functions that must be installed
early by the gc frontend
- to break cycles, for now we need two functions to convert between
*gc.Node and *types.Node (the latter is a dummy type)
- adjusted the gc's code to use the new package and the conversion
functions as needed
- made several Pkg, Sym, and Type methods functions as needed
- renamed constructors typ, typPtr, typArray, etc. to types.New,
types.NewPtr, types.NewArray, etc.
Passes toolstash-check -all.
Change-Id: I8adfa5e85c731645d0a7fd2030375ed6ebf54b72
Reviewed-on: https://go-review.googlesource.com/39855
Reviewed-by: Matthew Dempsky <mdempsky@google.com>
2017-04-04 17:54:02 -07:00
|
|
|
import "cmd/compile/internal/types"
|
|
|
|
|
2015-10-22 09:51:12 +09:00
|
|
|
// select
|
2015-02-13 14:40:36 -05:00
|
|
|
func typecheckselect(sel *Node) {
|
2015-03-02 14:22:05 -05:00
|
|
|
var def *Node
|
2016-03-02 17:34:42 -08:00
|
|
|
lno := setlineno(sel)
|
2016-03-19 17:02:01 -07:00
|
|
|
typecheckslice(sel.Ninit.Slice(), Etop)
|
2017-10-10 23:04:48 +01:00
|
|
|
for _, ncase := range sel.List.Slice() {
|
2015-02-13 14:40:36 -05:00
|
|
|
if ncase.Op != OXCASE {
|
2017-10-10 23:04:48 +01:00
|
|
|
setlineno(ncase)
|
2016-04-27 15:10:10 +10:00
|
|
|
Fatalf("typecheckselect %v", ncase.Op)
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
2016-03-08 15:10:26 -08:00
|
|
|
if ncase.List.Len() == 0 {
|
2015-02-13 14:40:36 -05:00
|
|
|
// default
|
|
|
|
if def != nil {
|
2017-10-10 23:04:48 +01:00
|
|
|
yyerrorl(ncase.Pos, "multiple defaults in select (first at %v)", def.Line())
|
2015-02-13 14:40:36 -05:00
|
|
|
} else {
|
|
|
|
def = ncase
|
|
|
|
}
|
2016-03-08 15:10:26 -08:00
|
|
|
} else if ncase.List.Len() > 1 {
|
2017-10-10 23:04:48 +01:00
|
|
|
yyerrorl(ncase.Pos, "select cases cannot be lists")
|
2015-02-13 14:40:36 -05:00
|
|
|
} else {
|
2017-02-19 15:57:58 +01:00
|
|
|
ncase.List.SetFirst(typecheck(ncase.List.First(), Etop))
|
2017-10-10 23:04:48 +01:00
|
|
|
n := ncase.List.First()
|
2015-02-13 14:40:36 -05:00
|
|
|
ncase.Left = n
|
2016-03-08 15:10:26 -08:00
|
|
|
ncase.List.Set(nil)
|
2015-02-13 14:40:36 -05:00
|
|
|
switch n.Op {
|
|
|
|
default:
|
2017-10-10 23:04:48 +01:00
|
|
|
yyerrorl(n.Pos, "select case must be receive, send or assign recv")
|
2015-02-13 14:40:36 -05:00
|
|
|
|
2016-09-24 21:38:58 +02:00
|
|
|
// convert x = <-c into OSELRECV(x, <-c).
|
2015-02-13 14:40:36 -05:00
|
|
|
// remove implicit conversions; the eventual assignment
|
|
|
|
// will reintroduce them.
|
|
|
|
case OAS:
|
2017-02-27 19:56:38 +02:00
|
|
|
if (n.Right.Op == OCONVNOP || n.Right.Op == OCONVIFACE) && n.Right.Implicit() {
|
2015-02-13 14:40:36 -05:00
|
|
|
n.Right = n.Right.Left
|
|
|
|
}
|
|
|
|
|
|
|
|
if n.Right.Op != ORECV {
|
2017-10-10 23:04:48 +01:00
|
|
|
yyerrorl(n.Pos, "select assignment must have receive on right hand side")
|
2015-02-13 14:40:36 -05:00
|
|
|
break
|
|
|
|
}
|
|
|
|
|
|
|
|
n.Op = OSELRECV
|
|
|
|
|
|
|
|
// convert x, ok = <-c into OSELRECV2(x, <-c) with ntest=ok
|
|
|
|
case OAS2RECV:
|
2016-03-08 15:10:26 -08:00
|
|
|
if n.Rlist.First().Op != ORECV {
|
2017-10-10 23:04:48 +01:00
|
|
|
yyerrorl(n.Pos, "select assignment must have receive on right hand side")
|
2015-02-13 14:40:36 -05:00
|
|
|
break
|
|
|
|
}
|
|
|
|
|
|
|
|
n.Op = OSELRECV2
|
2016-03-08 15:10:26 -08:00
|
|
|
n.Left = n.List.First()
|
2016-03-10 10:13:42 -08:00
|
|
|
n.List.Set1(n.List.Second())
|
2016-03-08 15:10:26 -08:00
|
|
|
n.Right = n.Rlist.First()
|
|
|
|
n.Rlist.Set(nil)
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
// convert <-c into OSELRECV(N, <-c)
|
|
|
|
case ORECV:
|
2017-10-10 23:04:48 +01:00
|
|
|
n = nodl(n.Pos, OSELRECV, nil, n)
|
2015-02-13 14:40:36 -05:00
|
|
|
|
2017-04-25 18:02:43 -07:00
|
|
|
n.SetTypecheck(1)
|
2015-02-13 14:40:36 -05:00
|
|
|
ncase.Left = n
|
|
|
|
|
|
|
|
case OSEND:
|
|
|
|
break
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-03-19 17:02:01 -07:00
|
|
|
typecheckslice(ncase.Nbody.Slice(), Etop)
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
2016-03-02 17:34:42 -08:00
|
|
|
lineno = lno
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
func walkselect(sel *Node) {
|
2017-10-22 17:18:51 +01:00
|
|
|
lno := setlineno(sel)
|
|
|
|
if sel.Nbody.Len() != 0 {
|
|
|
|
Fatalf("double walkselect")
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
2017-10-22 17:18:51 +01:00
|
|
|
init := sel.Ninit.Slice()
|
|
|
|
sel.Ninit.Set(nil)
|
|
|
|
|
|
|
|
init = append(init, walkselectcases(&sel.List)...)
|
|
|
|
sel.List.Set(nil)
|
|
|
|
|
|
|
|
sel.Nbody.Set(init)
|
|
|
|
walkstmtlist(sel.Nbody.Slice())
|
|
|
|
|
|
|
|
lineno = lno
|
|
|
|
}
|
|
|
|
|
|
|
|
func walkselectcases(cases *Nodes) []*Node {
|
|
|
|
n := cases.Len()
|
|
|
|
sellineno := lineno
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
// optimization: zero-case select
|
2017-10-22 17:18:51 +01:00
|
|
|
if n == 0 {
|
|
|
|
return []*Node{mkcall("block", nil, nil)}
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
// optimization: one-case select: single op.
|
2015-10-22 09:51:12 +09:00
|
|
|
// TODO(rsc): Reenable optimization once order.go can handle it.
|
2015-02-13 14:40:36 -05:00
|
|
|
// golang.org/issue/7672.
|
2017-10-22 17:18:51 +01:00
|
|
|
if n == 1 {
|
|
|
|
cas := cases.First()
|
2015-02-13 14:40:36 -05:00
|
|
|
setlineno(cas)
|
2016-03-08 15:10:26 -08:00
|
|
|
l := cas.Ninit.Slice()
|
2015-02-13 14:40:36 -05:00
|
|
|
if cas.Left != nil { // not default:
|
2015-02-23 16:07:24 -05:00
|
|
|
n := cas.Left
|
2016-03-08 15:10:26 -08:00
|
|
|
l = append(l, n.Ninit.Slice()...)
|
|
|
|
n.Ninit.Set(nil)
|
2015-02-23 16:07:24 -05:00
|
|
|
var ch *Node
|
2015-02-13 14:40:36 -05:00
|
|
|
switch n.Op {
|
|
|
|
default:
|
2016-04-27 15:10:10 +10:00
|
|
|
Fatalf("select %v", n.Op)
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
// ok already
|
|
|
|
case OSEND:
|
|
|
|
ch = n.Left
|
|
|
|
|
2015-04-01 09:38:44 -07:00
|
|
|
case OSELRECV, OSELRECV2:
|
2015-02-13 14:40:36 -05:00
|
|
|
ch = n.Right.Left
|
2016-03-08 15:10:26 -08:00
|
|
|
if n.Op == OSELRECV || n.List.Len() == 0 {
|
2015-02-13 14:40:36 -05:00
|
|
|
if n.Left == nil {
|
|
|
|
n = n.Right
|
|
|
|
} else {
|
|
|
|
n.Op = OAS
|
|
|
|
}
|
|
|
|
break
|
|
|
|
}
|
|
|
|
|
|
|
|
if n.Left == 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
|
|
|
nblank = typecheck(nblank, Erv|Easgn)
|
2015-02-13 14:40:36 -05:00
|
|
|
n.Left = nblank
|
|
|
|
}
|
|
|
|
|
|
|
|
n.Op = OAS2
|
2016-09-14 13:19:20 -07:00
|
|
|
n.List.Prepend(n.Left)
|
2016-03-10 10:13:42 -08:00
|
|
|
n.Rlist.Set1(n.Right)
|
2015-02-13 14:40:36 -05:00
|
|
|
n.Right = nil
|
|
|
|
n.Left = nil
|
2017-04-25 18:02:43 -07:00
|
|
|
n.SetTypecheck(0)
|
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
|
|
|
n = typecheck(n, Etop)
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
// if ch == nil { block() }; n;
|
2016-09-16 11:00:54 +10:00
|
|
|
a := nod(OIF, nil, nil)
|
2015-02-13 14:40:36 -05:00
|
|
|
|
2016-09-16 11:00:54 +10:00
|
|
|
a.Left = nod(OEQ, ch, nodnil())
|
2016-03-07 22:54:46 -08:00
|
|
|
var ln Nodes
|
|
|
|
ln.Set(l)
|
2016-03-10 10:13:42 -08:00
|
|
|
a.Nbody.Set1(mkcall("block", nil, &ln))
|
2016-03-07 22:54:46 -08:00
|
|
|
l = ln.Slice()
|
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)
|
2017-10-20 11:56:31 +01:00
|
|
|
l = append(l, a, n)
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
2016-03-04 16:13:17 -08:00
|
|
|
l = append(l, cas.Nbody.Slice()...)
|
2017-03-01 15:50:57 -08:00
|
|
|
l = append(l, nod(OBREAK, nil, nil))
|
2017-10-22 17:18:51 +01:00
|
|
|
return l
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
// convert case value arguments to addresses.
|
|
|
|
// this rewrite is used by both the general code and the next optimization.
|
2017-10-22 17:18:51 +01:00
|
|
|
for _, cas := range cases.Slice() {
|
2015-02-13 14:40:36 -05:00
|
|
|
setlineno(cas)
|
2017-10-22 17:18:51 +01:00
|
|
|
n := cas.Left
|
2015-02-13 14:40:36 -05:00
|
|
|
if n == nil {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
switch n.Op {
|
|
|
|
case OSEND:
|
2016-09-16 11:00:54 +10:00
|
|
|
n.Right = 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
|
|
|
n.Right = typecheck(n.Right, Erv)
|
2015-02-13 14:40:36 -05:00
|
|
|
|
2015-04-01 09:38:44 -07:00
|
|
|
case OSELRECV, OSELRECV2:
|
2016-03-08 15:10:26 -08:00
|
|
|
if n.Op == OSELRECV2 && n.List.Len() == 0 {
|
2015-02-13 14:40:36 -05:00
|
|
|
n.Op = OSELRECV
|
|
|
|
}
|
|
|
|
if n.Op == OSELRECV2 {
|
2017-02-19 15:57:58 +01:00
|
|
|
n.List.SetFirst(nod(OADDR, n.List.First(), nil))
|
|
|
|
n.List.SetFirst(typecheck(n.List.First(), Erv))
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
2017-03-07 14:26:27 -08:00
|
|
|
if n.Left != nil {
|
2016-09-16 11:00:54 +10:00
|
|
|
n.Left = nod(OADDR, n.Left, 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
|
|
|
n.Left = typecheck(n.Left, Erv)
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// optimization: two-case select but one is default: single non-blocking op.
|
2017-10-22 17:18:51 +01:00
|
|
|
if n == 2 && (cases.First().Left == nil || cases.Second().Left == nil) {
|
2015-02-23 16:07:24 -05:00
|
|
|
var cas *Node
|
|
|
|
var dflt *Node
|
2017-10-22 17:18:51 +01:00
|
|
|
if cases.First().Left == nil {
|
|
|
|
cas = cases.Second()
|
|
|
|
dflt = cases.First()
|
2015-02-13 14:40:36 -05:00
|
|
|
} else {
|
2017-10-22 17:18:51 +01:00
|
|
|
dflt = cases.Second()
|
|
|
|
cas = cases.First()
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
2015-02-23 16:07:24 -05:00
|
|
|
n := cas.Left
|
2015-02-13 14:40:36 -05:00
|
|
|
setlineno(n)
|
2016-09-16 11:00:54 +10:00
|
|
|
r := nod(OIF, nil, nil)
|
2016-03-08 15:10:26 -08:00
|
|
|
r.Ninit.Set(cas.Ninit.Slice())
|
2015-02-13 14:40:36 -05:00
|
|
|
switch n.Op {
|
|
|
|
default:
|
2016-04-27 15:10:10 +10:00
|
|
|
Fatalf("select %v", n.Op)
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
case OSEND:
|
2017-03-01 15:50:57 -08:00
|
|
|
// if selectnbsend(c, v) { body } else { default body }
|
2015-02-23 16:07:24 -05:00
|
|
|
ch := n.Left
|
cmd/compile: factor out Pkg, Sym, and Type into package types
- created new package cmd/compile/internal/types
- moved Pkg, Sym, Type to new package
- to break cycles, for now we need the (ugly) types/utils.go
file which contains a handful of functions that must be installed
early by the gc frontend
- to break cycles, for now we need two functions to convert between
*gc.Node and *types.Node (the latter is a dummy type)
- adjusted the gc's code to use the new package and the conversion
functions as needed
- made several Pkg, Sym, and Type methods functions as needed
- renamed constructors typ, typPtr, typArray, etc. to types.New,
types.NewPtr, types.NewArray, etc.
Passes toolstash-check -all.
Change-Id: I8adfa5e85c731645d0a7fd2030375ed6ebf54b72
Reviewed-on: https://go-review.googlesource.com/39855
Reviewed-by: Matthew Dempsky <mdempsky@google.com>
2017-04-04 17:54:02 -07:00
|
|
|
r.Left = mkcall1(chanfn("selectnbsend", 2, ch.Type), types.Types[TBOOL], &r.Ninit, ch, n.Right)
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
case OSELRECV:
|
2017-03-01 15:50:57 -08:00
|
|
|
// if c != nil && selectnbrecv(&v, c) { body } else { default body }
|
2016-09-16 11:00:54 +10:00
|
|
|
r = nod(OIF, nil, nil)
|
2016-03-08 15:10:26 -08:00
|
|
|
r.Ninit.Set(cas.Ninit.Slice())
|
2015-02-23 16:07:24 -05:00
|
|
|
ch := n.Right.Left
|
2017-03-07 14:26:27 -08:00
|
|
|
elem := n.Left
|
|
|
|
if elem == nil {
|
|
|
|
elem = nodnil()
|
|
|
|
}
|
|
|
|
r.Left = mkcall1(chanfn("selectnbrecv", 2, ch.Type), types.Types[TBOOL], &r.Ninit, elem, ch)
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
case OSELRECV2:
|
2017-03-01 15:50:57 -08:00
|
|
|
// if c != nil && selectnbrecv2(&v, c) { body } else { default body }
|
2016-09-16 11:00:54 +10:00
|
|
|
r = nod(OIF, nil, nil)
|
2016-03-08 15:10:26 -08:00
|
|
|
r.Ninit.Set(cas.Ninit.Slice())
|
2015-02-23 16:07:24 -05:00
|
|
|
ch := n.Right.Left
|
2017-03-07 14:26:27 -08:00
|
|
|
elem := n.Left
|
|
|
|
if elem == nil {
|
|
|
|
elem = nodnil()
|
|
|
|
}
|
|
|
|
r.Left = mkcall1(chanfn("selectnbrecv2", 2, ch.Type), types.Types[TBOOL], &r.Ninit, elem, n.List.First(), ch)
|
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
|
|
|
r.Left = typecheck(r.Left, Erv)
|
2016-02-27 14:31:33 -08:00
|
|
|
r.Nbody.Set(cas.Nbody.Slice())
|
2016-03-08 15:10:26 -08:00
|
|
|
r.Rlist.Set(append(dflt.Ninit.Slice(), dflt.Nbody.Slice()...))
|
2017-10-22 17:18:51 +01:00
|
|
|
return []*Node{r, nod(OBREAK, nil, nil)}
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
2017-10-22 17:18:51 +01:00
|
|
|
var init []*Node
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
// generate sel-struct
|
2017-10-22 17:18:51 +01:00
|
|
|
lineno = sellineno
|
runtime: eliminate runtime.hselect
Now the registration phase looks like:
var cases [4]runtime.scases
var order [8]uint16
selectsend(&cases[0], c1, &v1)
selectrecv(&cases[1], c2, &v2, nil)
selectrecv(&cases[2], c3, &v3, &ok)
selectdefault(&cases[3])
chosen := selectgo(&cases[0], &order[0], 4)
Primarily, this is just preparation for having the compiler open-code
selectsend, selectrecv, and selectdefault.
As a minor benefit, order can now be layed out separately on the stack
in the pointer-free segment, so it won't take up space in the
function's stack pointer maps.
Change-Id: I5552ba594201efd31fcb40084da20b42ea569a45
Reviewed-on: https://go-review.googlesource.com/37933
Run-TryBot: Matthew Dempsky <mdempsky@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Austin Clements <austin@google.com>
2017-03-07 13:44:53 -08:00
|
|
|
selv := temp(types.NewArray(scasetype(), int64(n)))
|
2017-10-22 17:18:51 +01:00
|
|
|
r := nod(OAS, selv, 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, Etop)
|
2016-02-27 14:31:33 -08:00
|
|
|
init = append(init, r)
|
runtime: eliminate runtime.hselect
Now the registration phase looks like:
var cases [4]runtime.scases
var order [8]uint16
selectsend(&cases[0], c1, &v1)
selectrecv(&cases[1], c2, &v2, nil)
selectrecv(&cases[2], c3, &v3, &ok)
selectdefault(&cases[3])
chosen := selectgo(&cases[0], &order[0], 4)
Primarily, this is just preparation for having the compiler open-code
selectsend, selectrecv, and selectdefault.
As a minor benefit, order can now be layed out separately on the stack
in the pointer-free segment, so it won't take up space in the
function's stack pointer maps.
Change-Id: I5552ba594201efd31fcb40084da20b42ea569a45
Reviewed-on: https://go-review.googlesource.com/37933
Run-TryBot: Matthew Dempsky <mdempsky@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Austin Clements <austin@google.com>
2017-03-07 13:44:53 -08:00
|
|
|
|
|
|
|
order := temp(types.NewArray(types.Types[TUINT16], 2*int64(n)))
|
|
|
|
r = nod(OAS, order, 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, Etop)
|
2016-02-27 14:31:33 -08:00
|
|
|
init = append(init, r)
|
2017-03-01 15:50:57 -08:00
|
|
|
|
2015-02-13 14:40:36 -05:00
|
|
|
// register cases
|
runtime: eliminate runtime.hselect
Now the registration phase looks like:
var cases [4]runtime.scases
var order [8]uint16
selectsend(&cases[0], c1, &v1)
selectrecv(&cases[1], c2, &v2, nil)
selectrecv(&cases[2], c3, &v3, &ok)
selectdefault(&cases[3])
chosen := selectgo(&cases[0], &order[0], 4)
Primarily, this is just preparation for having the compiler open-code
selectsend, selectrecv, and selectdefault.
As a minor benefit, order can now be layed out separately on the stack
in the pointer-free segment, so it won't take up space in the
function's stack pointer maps.
Change-Id: I5552ba594201efd31fcb40084da20b42ea569a45
Reviewed-on: https://go-review.googlesource.com/37933
Run-TryBot: Matthew Dempsky <mdempsky@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Austin Clements <austin@google.com>
2017-03-07 13:44:53 -08:00
|
|
|
for i, cas := range cases.Slice() {
|
2015-02-13 14:40:36 -05:00
|
|
|
setlineno(cas)
|
2017-03-01 15:50:57 -08:00
|
|
|
|
|
|
|
init = append(init, cas.Ninit.Slice()...)
|
2016-03-08 15:10:26 -08:00
|
|
|
cas.Ninit.Set(nil)
|
2015-02-13 14:40:36 -05:00
|
|
|
|
2017-03-07 14:26:27 -08:00
|
|
|
// Keep in sync with runtime/select.go.
|
|
|
|
const (
|
|
|
|
caseNil = iota
|
|
|
|
caseRecv
|
|
|
|
caseSend
|
|
|
|
caseDefault
|
|
|
|
)
|
|
|
|
|
|
|
|
var c, elem, receivedp *Node
|
|
|
|
var kind int64 = caseDefault
|
runtime: eliminate runtime.hselect
Now the registration phase looks like:
var cases [4]runtime.scases
var order [8]uint16
selectsend(&cases[0], c1, &v1)
selectrecv(&cases[1], c2, &v2, nil)
selectrecv(&cases[2], c3, &v3, &ok)
selectdefault(&cases[3])
chosen := selectgo(&cases[0], &order[0], 4)
Primarily, this is just preparation for having the compiler open-code
selectsend, selectrecv, and selectdefault.
As a minor benefit, order can now be layed out separately on the stack
in the pointer-free segment, so it won't take up space in the
function's stack pointer maps.
Change-Id: I5552ba594201efd31fcb40084da20b42ea569a45
Reviewed-on: https://go-review.googlesource.com/37933
Run-TryBot: Matthew Dempsky <mdempsky@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Austin Clements <austin@google.com>
2017-03-07 13:44:53 -08:00
|
|
|
|
2017-03-01 15:50:57 -08:00
|
|
|
if n := cas.Left; n != nil {
|
|
|
|
init = append(init, n.Ninit.Slice()...)
|
|
|
|
|
2015-02-13 14:40:36 -05:00
|
|
|
switch n.Op {
|
|
|
|
default:
|
2016-04-27 15:10:10 +10:00
|
|
|
Fatalf("select %v", n.Op)
|
2015-02-13 14:40:36 -05:00
|
|
|
case OSEND:
|
2017-03-07 14:26:27 -08:00
|
|
|
kind = caseSend
|
|
|
|
c = n.Left
|
|
|
|
elem = n.Right
|
2015-02-13 14:40:36 -05:00
|
|
|
case OSELRECV:
|
2017-03-07 14:26:27 -08:00
|
|
|
kind = caseRecv
|
|
|
|
c = n.Right.Left
|
|
|
|
elem = n.Left
|
2015-02-13 14:40:36 -05:00
|
|
|
case OSELRECV2:
|
2017-03-07 14:26:27 -08:00
|
|
|
kind = caseRecv
|
|
|
|
c = n.Right.Left
|
|
|
|
elem = n.Left
|
|
|
|
receivedp = n.List.First()
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-03-07 14:26:27 -08:00
|
|
|
setField := func(f string, val *Node) {
|
|
|
|
r := nod(OAS, nodSym(ODOT, nod(OINDEX, selv, nodintconst(int64(i))), lookup(f)), val)
|
|
|
|
r = typecheck(r, Etop)
|
|
|
|
init = append(init, r)
|
|
|
|
}
|
|
|
|
|
|
|
|
setField("kind", nodintconst(kind))
|
|
|
|
if c != nil {
|
|
|
|
c = nod(OCONVNOP, c, nil)
|
|
|
|
c.Type = types.Types[TUNSAFEPTR]
|
|
|
|
setField("c", c)
|
|
|
|
}
|
|
|
|
if elem != nil {
|
|
|
|
elem = nod(OCONVNOP, elem, nil)
|
|
|
|
elem.Type = types.Types[TUNSAFEPTR]
|
|
|
|
setField("elem", elem)
|
|
|
|
}
|
|
|
|
if receivedp != nil {
|
|
|
|
receivedp = nod(OCONVNOP, receivedp, nil)
|
|
|
|
receivedp.Type = types.NewPtr(types.Types[TBOOL])
|
|
|
|
setField("receivedp", receivedp)
|
|
|
|
}
|
|
|
|
|
|
|
|
// TODO(mdempsky): There should be a cleaner way to
|
|
|
|
// handle this.
|
|
|
|
if instrumenting {
|
|
|
|
r = mkcall("selectsetpc", nil, nil, bytePtrToIndex(selv, int64(i)))
|
|
|
|
init = append(init, r)
|
|
|
|
}
|
2017-03-01 15:50:57 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
// run the select
|
2017-10-22 17:18:51 +01:00
|
|
|
lineno = sellineno
|
|
|
|
chosen := temp(types.Types[TINT])
|
runtime: eliminate runtime.hselect
Now the registration phase looks like:
var cases [4]runtime.scases
var order [8]uint16
selectsend(&cases[0], c1, &v1)
selectrecv(&cases[1], c2, &v2, nil)
selectrecv(&cases[2], c3, &v3, &ok)
selectdefault(&cases[3])
chosen := selectgo(&cases[0], &order[0], 4)
Primarily, this is just preparation for having the compiler open-code
selectsend, selectrecv, and selectdefault.
As a minor benefit, order can now be layed out separately on the stack
in the pointer-free segment, so it won't take up space in the
function's stack pointer maps.
Change-Id: I5552ba594201efd31fcb40084da20b42ea569a45
Reviewed-on: https://go-review.googlesource.com/37933
Run-TryBot: Matthew Dempsky <mdempsky@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Austin Clements <austin@google.com>
2017-03-07 13:44:53 -08:00
|
|
|
r = nod(OAS, chosen, mkcall("selectgo", types.Types[TINT], nil, bytePtrToIndex(selv, 0), bytePtrToIndex(order, 0), nodintconst(int64(n))))
|
2017-03-01 15:50:57 -08:00
|
|
|
r = typecheck(r, Etop)
|
|
|
|
init = append(init, r)
|
|
|
|
|
runtime: eliminate runtime.hselect
Now the registration phase looks like:
var cases [4]runtime.scases
var order [8]uint16
selectsend(&cases[0], c1, &v1)
selectrecv(&cases[1], c2, &v2, nil)
selectrecv(&cases[2], c3, &v3, &ok)
selectdefault(&cases[3])
chosen := selectgo(&cases[0], &order[0], 4)
Primarily, this is just preparation for having the compiler open-code
selectsend, selectrecv, and selectdefault.
As a minor benefit, order can now be layed out separately on the stack
in the pointer-free segment, so it won't take up space in the
function's stack pointer maps.
Change-Id: I5552ba594201efd31fcb40084da20b42ea569a45
Reviewed-on: https://go-review.googlesource.com/37933
Run-TryBot: Matthew Dempsky <mdempsky@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Austin Clements <austin@google.com>
2017-03-07 13:44:53 -08:00
|
|
|
// selv and order are no longer alive after selectgo.
|
2017-03-01 15:50:57 -08:00
|
|
|
init = append(init, nod(OVARKILL, selv, nil))
|
runtime: eliminate runtime.hselect
Now the registration phase looks like:
var cases [4]runtime.scases
var order [8]uint16
selectsend(&cases[0], c1, &v1)
selectrecv(&cases[1], c2, &v2, nil)
selectrecv(&cases[2], c3, &v3, &ok)
selectdefault(&cases[3])
chosen := selectgo(&cases[0], &order[0], 4)
Primarily, this is just preparation for having the compiler open-code
selectsend, selectrecv, and selectdefault.
As a minor benefit, order can now be layed out separately on the stack
in the pointer-free segment, so it won't take up space in the
function's stack pointer maps.
Change-Id: I5552ba594201efd31fcb40084da20b42ea569a45
Reviewed-on: https://go-review.googlesource.com/37933
Run-TryBot: Matthew Dempsky <mdempsky@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Austin Clements <austin@google.com>
2017-03-07 13:44:53 -08:00
|
|
|
init = append(init, nod(OVARKILL, order, nil))
|
2017-03-01 15:50:57 -08:00
|
|
|
|
|
|
|
// dispatch cases
|
2017-10-22 17:18:51 +01:00
|
|
|
for i, cas := range cases.Slice() {
|
2017-03-01 15:50:57 -08:00
|
|
|
setlineno(cas)
|
2015-02-13 14:40:36 -05:00
|
|
|
|
2017-03-01 15:50:57 -08:00
|
|
|
cond := nod(OEQ, chosen, nodintconst(int64(i)))
|
|
|
|
cond = typecheck(cond, Erv)
|
cmd/compile: prevent untyped types from reaching walk
We already require expressions to have already been typechecked before
reaching walk. Moreover, all untyped expressions should have been
converted to their default type by walk.
However, in practice, we've been somewhat sloppy and inconsistent
about ensuring this. In particular, a lot of AST rewrites ended up
leaving untyped bool expressions scattered around. These likely aren't
harmful in practice, but it seems worth cleaning up.
The two most common cases addressed by this CL are:
1) When generating OIF and OFOR nodes, we would often typecheck the
conditional expression, but not apply defaultlit to force it to the
expression's default type.
2) When rewriting string comparisons into more fundamental primitives,
we were simply overwriting r.Type with the desired type, which didn't
propagate the type to nested subexpressions. These are fixed by
utilizing finishcompare, which correctly handles this (and is already
used by other comparison lowering rewrites).
Lastly, walkexpr is extended to assert that it's not called on untyped
expressions.
Fixes #23834.
Change-Id: Icbd29648a293555e4015d3b06a95a24ccbd3f790
Reviewed-on: https://go-review.googlesource.com/98337
Reviewed-by: Robert Griesemer <gri@golang.org>
2018-03-02 15:20:49 -08:00
|
|
|
cond = defaultlit(cond, nil)
|
2017-03-01 15:50:57 -08:00
|
|
|
|
|
|
|
r = nod(OIF, cond, nil)
|
2016-03-07 22:54:46 -08:00
|
|
|
r.Nbody.AppendNodes(&cas.Nbody)
|
2016-09-16 11:00:54 +10:00
|
|
|
r.Nbody.Append(nod(OBREAK, nil, nil))
|
2016-02-27 14:31:33 -08:00
|
|
|
init = append(init, r)
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
2017-10-22 17:18:51 +01:00
|
|
|
return init
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
runtime: eliminate runtime.hselect
Now the registration phase looks like:
var cases [4]runtime.scases
var order [8]uint16
selectsend(&cases[0], c1, &v1)
selectrecv(&cases[1], c2, &v2, nil)
selectrecv(&cases[2], c3, &v3, &ok)
selectdefault(&cases[3])
chosen := selectgo(&cases[0], &order[0], 4)
Primarily, this is just preparation for having the compiler open-code
selectsend, selectrecv, and selectdefault.
As a minor benefit, order can now be layed out separately on the stack
in the pointer-free segment, so it won't take up space in the
function's stack pointer maps.
Change-Id: I5552ba594201efd31fcb40084da20b42ea569a45
Reviewed-on: https://go-review.googlesource.com/37933
Run-TryBot: Matthew Dempsky <mdempsky@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Austin Clements <austin@google.com>
2017-03-07 13:44:53 -08:00
|
|
|
// bytePtrToIndex returns a Node representing "(*byte)(&n[i])".
|
|
|
|
func bytePtrToIndex(n *Node, i int64) *Node {
|
|
|
|
s := nod(OCONVNOP, nod(OADDR, nod(OINDEX, n, nodintconst(i)), nil), nil)
|
|
|
|
s.Type = types.NewPtr(types.Types[TUINT8])
|
|
|
|
s = typecheck(s, Erv)
|
|
|
|
return s
|
|
|
|
}
|
|
|
|
|
|
|
|
var scase *types.Type
|
|
|
|
|
2016-03-17 04:58:34 -07:00
|
|
|
// Keep in sync with src/runtime/select.go.
|
runtime: eliminate runtime.hselect
Now the registration phase looks like:
var cases [4]runtime.scases
var order [8]uint16
selectsend(&cases[0], c1, &v1)
selectrecv(&cases[1], c2, &v2, nil)
selectrecv(&cases[2], c3, &v3, &ok)
selectdefault(&cases[3])
chosen := selectgo(&cases[0], &order[0], 4)
Primarily, this is just preparation for having the compiler open-code
selectsend, selectrecv, and selectdefault.
As a minor benefit, order can now be layed out separately on the stack
in the pointer-free segment, so it won't take up space in the
function's stack pointer maps.
Change-Id: I5552ba594201efd31fcb40084da20b42ea569a45
Reviewed-on: https://go-review.googlesource.com/37933
Run-TryBot: Matthew Dempsky <mdempsky@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Austin Clements <austin@google.com>
2017-03-07 13:44:53 -08:00
|
|
|
func scasetype() *types.Type {
|
|
|
|
if scase == nil {
|
|
|
|
scase = tostruct([]*Node{
|
2017-03-07 14:26:27 -08:00
|
|
|
namedfield("c", types.Types[TUNSAFEPTR]),
|
|
|
|
namedfield("elem", types.Types[TUNSAFEPTR]),
|
|
|
|
namedfield("receivedp", types.NewPtr(types.Types[TBOOL])),
|
runtime: eliminate runtime.hselect
Now the registration phase looks like:
var cases [4]runtime.scases
var order [8]uint16
selectsend(&cases[0], c1, &v1)
selectrecv(&cases[1], c2, &v2, nil)
selectrecv(&cases[2], c3, &v3, &ok)
selectdefault(&cases[3])
chosen := selectgo(&cases[0], &order[0], 4)
Primarily, this is just preparation for having the compiler open-code
selectsend, selectrecv, and selectdefault.
As a minor benefit, order can now be layed out separately on the stack
in the pointer-free segment, so it won't take up space in the
function's stack pointer maps.
Change-Id: I5552ba594201efd31fcb40084da20b42ea569a45
Reviewed-on: https://go-review.googlesource.com/37933
Run-TryBot: Matthew Dempsky <mdempsky@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Austin Clements <austin@google.com>
2017-03-07 13:44:53 -08:00
|
|
|
namedfield("kind", types.Types[TUINT16]),
|
2017-03-07 14:26:27 -08:00
|
|
|
namedfield("pc", types.Types[TUINTPTR]),
|
runtime: eliminate runtime.hselect
Now the registration phase looks like:
var cases [4]runtime.scases
var order [8]uint16
selectsend(&cases[0], c1, &v1)
selectrecv(&cases[1], c2, &v2, nil)
selectrecv(&cases[2], c3, &v3, &ok)
selectdefault(&cases[3])
chosen := selectgo(&cases[0], &order[0], 4)
Primarily, this is just preparation for having the compiler open-code
selectsend, selectrecv, and selectdefault.
As a minor benefit, order can now be layed out separately on the stack
in the pointer-free segment, so it won't take up space in the
function's stack pointer maps.
Change-Id: I5552ba594201efd31fcb40084da20b42ea569a45
Reviewed-on: https://go-review.googlesource.com/37933
Run-TryBot: Matthew Dempsky <mdempsky@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Austin Clements <austin@google.com>
2017-03-07 13:44:53 -08:00
|
|
|
namedfield("releasetime", types.Types[TUINT64]),
|
|
|
|
})
|
|
|
|
scase.SetNoalg(true)
|
|
|
|
}
|
|
|
|
return scase
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|