]> Cypherpunks.ru repositories - gostls13.git/commitdiff
cmd/compile: scanning closures body when visiting wrapper function
authorCuong Manh Le <cuong.manhle.vn@gmail.com>
Thu, 22 Jun 2023 18:04:29 +0000 (01:04 +0700)
committerGopher Robot <gobot@golang.org>
Fri, 23 Jun 2023 14:29:16 +0000 (14:29 +0000)
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 <gobot@golang.org>
Reviewed-by: Than McIntosh <thanm@google.com>
Reviewed-by: Matthew Dempsky <mdempsky@google.com>
Run-TryBot: Cuong Manh Le <cuong.manhle.vn@gmail.com>
Auto-Submit: Cuong Manh Le <cuong.manhle.vn@gmail.com>

src/cmd/compile/internal/ir/visit.go
src/cmd/compile/internal/noder/reader.go
test/fixedbugs/issue60945.dir/a.go [new file with mode: 0644]
test/fixedbugs/issue60945.dir/b.go [new file with mode: 0644]
test/fixedbugs/issue60945.go [new file with mode: 0644]

index 016467081e5d9e6ae7d6f1f1a2eb7f9a387a6bd8..73ec1de544c08fa552b6c5b3fb89ed960e1e4cc6 100644 (file)
@@ -115,6 +115,17 @@ func VisitList(list Nodes, visit func(Node)) {
        }
 }
 
+// VisitFuncAndClosures calls visit on each non-nil node in fn.Body,
+// including any nested closure bodies.
+func VisitFuncAndClosures(fn *Func, visit func(n Node)) {
+       VisitList(fn.Body, func(n Node) {
+               visit(n)
+               if n, ok := n.(*ClosureExpr); ok && n.Op() == OCLOSURE {
+                       VisitFuncAndClosures(n.Func, visit)
+               }
+       })
+}
+
 // Any looks for a non-nil node x in the IR tree rooted at n
 // for which cond(x) returns true.
 // Any considers nodes in a depth-first, preorder traversal.
index 70f51e2253e119ad1c120e954d3ce83bb311cbd2..610d02c07c90fd6e57196ad6eb0cf884c30921e7 100644 (file)
@@ -3919,7 +3919,11 @@ func finishWrapperFunc(fn *ir.Func, target *ir.Package) {
        // The body of wrapper function after inlining may reveal new ir.OMETHVALUE node,
        // we don't know whether wrapper function has been generated for it or not, so
        // generate one immediately here.
-       ir.VisitList(fn.Body, func(n ir.Node) {
+       //
+       // Further, after CL 492017, function that construct closures is allowed to be inlined,
+       // even though the closure itself can't be inline. So we also need to visit body of any
+       // closure that we see when visiting body of the wrapper function.
+       ir.VisitFuncAndClosures(fn, func(n ir.Node) {
                if n, ok := n.(*ir.SelectorExpr); ok && n.Op() == ir.OMETHVALUE {
                        wrapMethodValue(n.X.Type(), n.Selection, target, true)
                }
diff --git a/test/fixedbugs/issue60945.dir/a.go b/test/fixedbugs/issue60945.dir/a.go
new file mode 100644 (file)
index 0000000..663a0cf
--- /dev/null
@@ -0,0 +1,22 @@
+// Copyright 2023 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 a
+
+type S struct{}
+
+func callClosure(closure func()) {
+       closure()
+}
+
+func (s *S) M() {
+       callClosure(func() {
+               defer f(s.m) // prevent closures to be inlined.
+       })
+}
+
+func (s *S) m() {}
+
+//go:noinline
+func f(a ...any) {}
diff --git a/test/fixedbugs/issue60945.dir/b.go b/test/fixedbugs/issue60945.dir/b.go
new file mode 100644 (file)
index 0000000..e60d9dc
--- /dev/null
@@ -0,0 +1,9 @@
+// Copyright 2023 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 b
+
+import "./a"
+
+var _ = (&a.S{}).M
diff --git a/test/fixedbugs/issue60945.go b/test/fixedbugs/issue60945.go
new file mode 100644 (file)
index 0000000..5c4c5c0
--- /dev/null
@@ -0,0 +1,7 @@
+// compiledir
+
+// Copyright 2023 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 ignored