aboutsummaryrefslogtreecommitdiff
path: root/src/cmd/compile/internal/reflectdata/reflect.go
diff options
context:
space:
mode:
Diffstat (limited to 'src/cmd/compile/internal/reflectdata/reflect.go')
-rw-r--r--src/cmd/compile/internal/reflectdata/reflect.go21
1 files changed, 18 insertions, 3 deletions
diff --git a/src/cmd/compile/internal/reflectdata/reflect.go b/src/cmd/compile/internal/reflectdata/reflect.go
index aec7358c322..4ee9830db38 100644
--- a/src/cmd/compile/internal/reflectdata/reflect.go
+++ b/src/cmd/compile/internal/reflectdata/reflect.go
@@ -1878,14 +1878,14 @@ func methodWrapper(rcvr *types.Type, method *types.Field, forItab bool) *obj.LSy
// the TOC to the appropriate value for that module. But if it returns
// directly to the wrapper's caller, nothing will reset it to the correct
// value for that function.
+ var call *ir.CallExpr
if !base.Flag.Cfg.Instrumenting && rcvr.IsPtr() && methodrcvr.IsPtr() && method.Embedded != 0 && !types.IsInterfaceMethod(method.Type) && !(base.Ctxt.Arch.Name == "ppc64le" && base.Ctxt.Flag_dynlink) && !generic {
- call := ir.NewCallExpr(base.Pos, ir.OCALL, dot, nil)
+ call = ir.NewCallExpr(base.Pos, ir.OCALL, dot, nil)
call.Args = ir.ParamNames(tfn.Type())
call.IsDDD = tfn.Type().IsVariadic()
fn.Body.Append(ir.NewTailCallStmt(base.Pos, call))
} else {
fn.SetWrapper(true) // ignore frame for panic+recover matching
- var call *ir.CallExpr
if generic && dot.X != nthis {
// If there is embedding involved, then we should do the
@@ -1970,7 +1970,22 @@ func methodWrapper(rcvr *types.Type, method *types.Field, forItab bool) *obj.LSy
typecheck.Stmts(fn.Body)
if AfterGlobalEscapeAnalysis {
- inline.InlineCalls(fn)
+ // Inlining the method may reveal closures, which require walking all function bodies
+ // to decide whether to capture free variables by value or by ref. So we only do inline
+ // if the method do not contain any closures, otherwise, the escape analysis may make
+ // dead variables resurrected, and causing liveness analysis confused, see issue #53702.
+ var canInline bool
+ switch x := call.X.(type) {
+ case *ir.Name:
+ canInline = len(x.Func.Closures) == 0
+ case *ir.SelectorExpr:
+ if x.Op() == ir.OMETHEXPR {
+ canInline = x.FuncName().Func != nil && len(x.FuncName().Func.Closures) == 0
+ }
+ }
+ if canInline {
+ inline.InlineCalls(fn)
+ }
escape.Batch([]*ir.Func{fn}, false)
}