Skip to content

Commit 6dce882

Browse files
cuonglmgopherbot
authored andcommitted
cmd/compile: scanning closures body when visiting wrapper function
CL 410344 fixed missing method value wrapper, by visiting body of wrapper function after applying inlining pass. CL 492017 allow more inlining of functions that construct closures, which ends up making the wrapper function now inlineable, but can contain closure nodes that couldn't be inlined. These closures body may contain OMETHVALUE nodes that we never seen, thus we need to scan closures body for finding them. Fixes #60945 Change-Id: Ia1e31420bb172ff87d7321d2da2989ef23e6ebb6 Reviewed-on: https://go-review.googlesource.com/c/go/+/505255 TryBot-Result: Gopher Robot <[email protected]> Reviewed-by: Than McIntosh <[email protected]> Reviewed-by: Matthew Dempsky <[email protected]> Run-TryBot: Cuong Manh Le <[email protected]> Auto-Submit: Cuong Manh Le <[email protected]>
1 parent 164acee commit 6dce882

File tree

5 files changed

+54
-1
lines changed

5 files changed

+54
-1
lines changed

src/cmd/compile/internal/ir/visit.go

+11
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,17 @@ func VisitList(list Nodes, visit func(Node)) {
115115
}
116116
}
117117

118+
// VisitFuncAndClosures calls visit on each non-nil node in fn.Body,
119+
// including any nested closure bodies.
120+
func VisitFuncAndClosures(fn *Func, visit func(n Node)) {
121+
VisitList(fn.Body, func(n Node) {
122+
visit(n)
123+
if n, ok := n.(*ClosureExpr); ok && n.Op() == OCLOSURE {
124+
VisitFuncAndClosures(n.Func, visit)
125+
}
126+
})
127+
}
128+
118129
// Any looks for a non-nil node x in the IR tree rooted at n
119130
// for which cond(x) returns true.
120131
// Any considers nodes in a depth-first, preorder traversal.

src/cmd/compile/internal/noder/reader.go

+5-1
Original file line numberDiff line numberDiff line change
@@ -3919,7 +3919,11 @@ func finishWrapperFunc(fn *ir.Func, target *ir.Package) {
39193919
// The body of wrapper function after inlining may reveal new ir.OMETHVALUE node,
39203920
// we don't know whether wrapper function has been generated for it or not, so
39213921
// generate one immediately here.
3922-
ir.VisitList(fn.Body, func(n ir.Node) {
3922+
//
3923+
// Further, after CL 492017, function that construct closures is allowed to be inlined,
3924+
// even though the closure itself can't be inline. So we also need to visit body of any
3925+
// closure that we see when visiting body of the wrapper function.
3926+
ir.VisitFuncAndClosures(fn, func(n ir.Node) {
39233927
if n, ok := n.(*ir.SelectorExpr); ok && n.Op() == ir.OMETHVALUE {
39243928
wrapMethodValue(n.X.Type(), n.Selection, target, true)
39253929
}

test/fixedbugs/issue60945.dir/a.go

+22
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
// Copyright 2023 The Go Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style
3+
// license that can be found in the LICENSE file.
4+
5+
package a
6+
7+
type S struct{}
8+
9+
func callClosure(closure func()) {
10+
closure()
11+
}
12+
13+
func (s *S) M() {
14+
callClosure(func() {
15+
defer f(s.m) // prevent closures to be inlined.
16+
})
17+
}
18+
19+
func (s *S) m() {}
20+
21+
//go:noinline
22+
func f(a ...any) {}

test/fixedbugs/issue60945.dir/b.go

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
// Copyright 2023 The Go Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style
3+
// license that can be found in the LICENSE file.
4+
5+
package b
6+
7+
import "./a"
8+
9+
var _ = (&a.S{}).M

test/fixedbugs/issue60945.go

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
// compiledir
2+
3+
// Copyright 2023 The Go Authors. All rights reserved.
4+
// Use of this source code is governed by a BSD-style
5+
// license that can be found in the LICENSE file.
6+
7+
package ignored

0 commit comments

Comments
 (0)