Skip to content

Commit 93f10b8

Browse files
cuonglmgopherbot
authored andcommitted
cmd/compile: fix wrong escape analysis for go/defer generic calls
For go/defer calls like "defer f(x, y)", the compiler rewrites it to: x1, y1 := x, y defer func() { f(x1, y1) }() However, if "f" needs runtime type information, the "RType" field will refer to the outer ".dict" param, causing wrong liveness analysis. To fix this, if "f" refers to outer ".dict", the dict param will be copied to an autotmp, and "f" will refer to this autotmp instead. Fixes #58341 Change-Id: I238b6e75441442b5540d39bc818205398e80c94d Reviewed-on: https://go-review.googlesource.com/c/go/+/466035 Reviewed-by: David Chase <[email protected]> Auto-Submit: Cuong Manh Le <[email protected]> Reviewed-by: Matthew Dempsky <[email protected]> Run-TryBot: Cuong Manh Le <[email protected]> TryBot-Result: Gopher Robot <[email protected]>
1 parent 1e9925f commit 93f10b8

File tree

2 files changed

+47
-1
lines changed

2 files changed

+47
-1
lines changed

src/cmd/compile/internal/escape/call.go

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ func (e *escape) call(ks []hole, call ir.Node) {
1919
var init ir.Nodes
2020
e.callCommon(ks, call, &init, nil)
2121
if len(init) != 0 {
22-
call.(*ir.CallExpr).PtrInit().Append(init...)
22+
call.(ir.InitNode).PtrInit().Append(init...)
2323
}
2424
}
2525

@@ -38,6 +38,18 @@ func (e *escape) callCommon(ks []hole, call ir.Node, init *ir.Nodes, wrapper *ir
3838
argumentFunc(nil, k, argp)
3939
}
4040

41+
argumentRType := func(rtypep *ir.Node) {
42+
rtype := *rtypep
43+
if rtype == nil {
44+
return
45+
}
46+
// common case: static rtype/itab argument, which can be evaluated within the wrapper instead.
47+
if addr, ok := rtype.(*ir.AddrExpr); ok && addr.Op() == ir.OADDR && addr.X.Op() == ir.OLINKSYMOFFSET {
48+
return
49+
}
50+
e.wrapExpr(rtype.Pos(), rtypep, init, call, wrapper)
51+
}
52+
4153
switch call.Op() {
4254
default:
4355
ir.Dump("esc", call)
@@ -152,6 +164,7 @@ func (e *escape) callCommon(ks []hole, call ir.Node, init *ir.Nodes, wrapper *ir
152164
argument(e.heapHole(), &args[i])
153165
}
154166
}
167+
argumentRType(&call.RType)
155168

156169
case ir.OCOPY:
157170
call := call.(*ir.BinaryExpr)
@@ -162,6 +175,7 @@ func (e *escape) callCommon(ks []hole, call ir.Node, init *ir.Nodes, wrapper *ir
162175
copiedK = e.heapHole().deref(call, "copied slice")
163176
}
164177
argument(copiedK, &call.Y)
178+
argumentRType(&call.RType)
165179

166180
case ir.OPANIC:
167181
call := call.(*ir.UnaryExpr)
@@ -178,6 +192,7 @@ func (e *escape) callCommon(ks []hole, call ir.Node, init *ir.Nodes, wrapper *ir
178192
for i := range call.Args {
179193
argument(e.discardHole(), &call.Args[i])
180194
}
195+
argumentRType(&call.RType)
181196

182197
case ir.OLEN, ir.OCAP, ir.OREAL, ir.OIMAG, ir.OCLOSE, ir.OCLEAR:
183198
call := call.(*ir.UnaryExpr)
@@ -191,6 +206,7 @@ func (e *escape) callCommon(ks []hole, call ir.Node, init *ir.Nodes, wrapper *ir
191206
call := call.(*ir.BinaryExpr)
192207
argument(ks[0], &call.X)
193208
argument(e.discardHole(), &call.Y)
209+
argumentRType(&call.RType)
194210
}
195211
}
196212

test/fixedbugs/issue58341.go

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
// compile
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 p
8+
9+
type S[T comparable] struct {
10+
m map[T]T
11+
}
12+
13+
func (s S[T]) M1(node T) {
14+
defer delete(s.m, node)
15+
}
16+
17+
func (s S[T]) M2(node T) {
18+
defer func() {
19+
delete(s.m, node)
20+
}()
21+
}
22+
23+
func (s S[T]) M3(node T) {
24+
defer f(s.m, node)
25+
}
26+
27+
//go:noinline
28+
func f[T comparable](map[T]T, T) {}
29+
30+
var _ = S[int]{}

0 commit comments

Comments
 (0)