diff options
author | Matthew Dempsky <mdempsky@google.com> | 2023-08-15 16:45:52 -0700 |
---|---|---|
committer | Gopher Robot <gobot@golang.org> | 2023-08-17 16:36:09 +0000 |
commit | ff47dd1d665d30d5f3d26f031192afebb4422c3c (patch) | |
tree | b688caf64d48a7c96cbce1e36ce10c865f8418d9 /test/escape_closure.go | |
parent | f278ae61d551ebd12956a1ed21ad6131495a2513 (diff) | |
download | go-ff47dd1d665d30d5f3d26f031192afebb4422c3c.tar.gz go-ff47dd1d665d30d5f3d26f031192afebb4422c3c.zip |
cmd/compile/internal/escape: optimize indirect closure calls
This CL extends escape analysis in two ways.
First, we already optimize directly called closures. For example,
given:
var x int // already stack allocated today
p := func() *int { return &x }()
we don't need to move x to the heap, because we can statically track
where &x flows. This CL extends the same idea to work for indirectly
called closures too, as long as we know everywhere that they're
called. For example:
var x int // stack allocated after this CL
f := func() *int { return &x }
p := f()
This will allow a subsequent CL to move the generation of go/defer
wrappers earlier.
Second, this CL adds tracking to detect when pointer values flow to
the pointee operand of an indirect assignment statement (i.e., flows
to p in "*p = x") or to builtins that modify memory (append, copy,
clear). This isn't utilized in the current CL, but a subsequent CL
will make use of it to better optimize string->[]byte conversions.
Updates #2205.
Change-Id: I610f9c531e135129c947684833e288ce64406f35
Reviewed-on: https://go-review.googlesource.com/c/go/+/520259
Run-TryBot: Matthew Dempsky <mdempsky@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Auto-Submit: Matthew Dempsky <mdempsky@google.com>
Reviewed-by: Cuong Manh Le <cuong.manhle.vn@gmail.com>
Reviewed-by: Dmitri Shuralyov <dmitshur@google.com>
Diffstat (limited to 'test/escape_closure.go')
-rw-r--r-- | test/escape_closure.go | 14 |
1 files changed, 14 insertions, 0 deletions
diff --git a/test/escape_closure.go b/test/escape_closure.go index bd6c025476..0b19d6f6e8 100644 --- a/test/escape_closure.go +++ b/test/escape_closure.go @@ -177,3 +177,17 @@ func ClosureIndirect() { } func nopFunc(p *int) {} // ERROR "p does not escape" + +func ClosureIndirect2() { + f := func(p *int) *int { return p } // ERROR "leaking param: p to result ~r0 level=0" "func literal does not escape" + + f(new(int)) // ERROR "new\(int\) does not escape" + + g := f + g(new(int)) // ERROR "new\(int\) does not escape" + + h := nopFunc2 + h(new(int)) // ERROR "new\(int\) does not escape" +} + +func nopFunc2(p *int) *int { return p } // ERROR "leaking param: p to result ~r0 level=0" |