aboutsummaryrefslogtreecommitdiff
path: root/src/cmd/compile/internal/escape
diff options
context:
space:
mode:
authorMatthew Dempsky <mdempsky@google.com>2021-06-23 00:49:03 -0700
committerMatthew Dempsky <mdempsky@google.com>2021-06-23 16:48:35 +0000
commita72a499c24cfcfce2a16ac7c228c2c914c4f36c4 (patch)
tree19042a1078728d438c7c3970ea63e5b209577b99 /src/cmd/compile/internal/escape
parenteb691fdd62c9f1dc36c9c9a974ac2ddad677fd99 (diff)
downloadgo-a72a499c24cfcfce2a16ac7c228c2c914c4f36c4.tar.gz
go-a72a499c24cfcfce2a16ac7c228c2c914c4f36c4.zip
[dev.typeparams] cmd/compile: optimize wrapping of constant arguments
When wrapping a go/defer statement like: go f(g(), "x", 42) we were wrapping it like: _0, _1, _2, _3 := f, g(), "x", 42 go func() { _0(_1, _2, _3) }() This is simple and general (and often necessary), but suboptimal in some cases, such as this. Instead of evaluating the constant arguments at the go/defer statement, and storing them into the closure context, we can just keep them in the wrapped call expression. This CL changes the code to instead generate (assuming f is a declared function, not a function-typed variable): _0 := g() go func() { f(_0, "x", 42) }() Change-Id: I2bdd4951e7ee93363e1656ecf9b5bd69a121c38a Reviewed-on: https://go-review.googlesource.com/c/go/+/330332 Run-TryBot: Matthew Dempsky <mdempsky@google.com> TryBot-Result: Go Bot <gobot@golang.org> Trust: Matthew Dempsky <mdempsky@google.com> Reviewed-by: Cuong Manh Le <cuong.manhle.vn@gmail.com>
Diffstat (limited to 'src/cmd/compile/internal/escape')
-rw-r--r--src/cmd/compile/internal/escape/call.go12
1 files changed, 12 insertions, 0 deletions
diff --git a/src/cmd/compile/internal/escape/call.go b/src/cmd/compile/internal/escape/call.go
index 850b9cbde2..b8e28cd46a 100644
--- a/src/cmd/compile/internal/escape/call.go
+++ b/src/cmd/compile/internal/escape/call.go
@@ -293,6 +293,18 @@ func (e *escape) rewriteArgument(argp *ir.Node, init *ir.Nodes, call ir.Node, fn
}
visit := func(pos src.XPos, argp *ir.Node) {
+ // Optimize a few common constant expressions. By leaving these
+ // untouched in the call expression, we let the wrapper handle
+ // evaluating them, rather than taking up closure context space.
+ switch arg := *argp; arg.Op() {
+ case ir.OLITERAL, ir.ONIL, ir.OMETHEXPR:
+ return
+ case ir.ONAME:
+ if arg.(*ir.Name).Class == ir.PFUNC {
+ return
+ }
+ }
+
if unsafeUintptr(*argp) {
return
}