aboutsummaryrefslogtreecommitdiff
path: root/src/cmd/compile/internal/liveness
diff options
context:
space:
mode:
authorCherry Zhang <cherryyz@google.com>2021-04-16 17:29:38 -0400
committerCherry Zhang <cherryyz@google.com>2021-04-19 23:17:10 +0000
commit3711ea0b5d1bc381bda02ec3fe16369ed997eda6 (patch)
treed4abb93a3dbe09ccc5c4a4f79055ed4f76fd2142 /src/cmd/compile/internal/liveness
parentb3a5640397e887514a860b9eb73e125c2b650f7b (diff)
downloadgo-3711ea0b5d1bc381bda02ec3fe16369ed997eda6.tar.gz
go-3711ea0b5d1bc381bda02ec3fe16369ed997eda6.zip
cmd/compile: do not clobber arguments for reflect.callReflect and callMethod's ABI wrappers
reflect.callReflect and reflect.callMethod are called from special functions makeFuncStub and methodValueCall. The runtime expects that it can find the first argument (ctxt) at 0(SP) in makeFuncStub and methodValueCall's frame. Normally callReflect and callMethod already do not modify the argument, and keep it alive. But the compiler-generated ABI wrappers don't do that. Special case the wrappers to not clobber its arguments. Change-Id: I1769f49b81c38eabe452d561001c418352814d86 Reviewed-on: https://go-review.googlesource.com/c/go/+/310889 Trust: Cherry Zhang <cherryyz@google.com> Run-TryBot: Cherry Zhang <cherryyz@google.com> TryBot-Result: Go Bot <gobot@golang.org> Reviewed-by: Than McIntosh <thanm@google.com>
Diffstat (limited to 'src/cmd/compile/internal/liveness')
-rw-r--r--src/cmd/compile/internal/liveness/plive.go23
1 files changed, 19 insertions, 4 deletions
diff --git a/src/cmd/compile/internal/liveness/plive.go b/src/cmd/compile/internal/liveness/plive.go
index 9eca05b040..424d248590 100644
--- a/src/cmd/compile/internal/liveness/plive.go
+++ b/src/cmd/compile/internal/liveness/plive.go
@@ -146,7 +146,8 @@ type liveness struct {
// a part of it is used, but we may not initialize all parts.
partLiveArgs map[*ir.Name]bool
- doClobber bool // Whether to clobber dead stack slots in this function.
+ doClobber bool // Whether to clobber dead stack slots in this function.
+ noClobberArgs bool // Do not clobber function arguments
}
// Map maps from *ssa.Value to LivenessIndex.
@@ -930,16 +931,27 @@ func (lv *liveness) enableClobber() {
// Otherwise, giant functions make this experiment generate too much code.
return
}
- if lv.f.Name == "forkAndExecInChild" || lv.f.Name == "wbBufFlush" {
+ if lv.f.Name == "forkAndExecInChild" {
// forkAndExecInChild calls vfork on some platforms.
// The code we add here clobbers parts of the stack in the child.
// When the parent resumes, it is using the same stack frame. But the
// child has clobbered stack variables that the parent needs. Boom!
// In particular, the sys argument gets clobbered.
- //
+ return
+ }
+ if lv.f.Name == "wbBufFlush" ||
+ ((lv.f.Name == "callReflect" || lv.f.Name == "callMethod") && lv.fn.ABIWrapper()) {
// runtime.wbBufFlush must not modify its arguments. See the comments
// in runtime/mwbbuf.go:wbBufFlush.
- return
+ //
+ // reflect.callReflect and reflect.callMethod are called from special
+ // functions makeFuncStub and methodValueCall. The runtime expects
+ // that it can find the first argument (ctxt) at 0(SP) in makeFuncStub
+ // and methodValueCall's frame (see runtime/traceback.go:getArgInfo).
+ // Normally callReflect and callMethod already do not modify the
+ // argument, and keep it alive. But the compiler-generated ABI wrappers
+ // don't do that. Special case the wrappers to not clobber its arguments.
+ lv.noClobberArgs = true
}
if h := os.Getenv("GOCLOBBERDEADHASH"); h != "" {
// Clobber only functions where the hash of the function name matches a pattern.
@@ -1000,6 +1012,9 @@ func clobber(lv *liveness, b *ssa.Block, live bitvec.BitVec) {
// tracked dynamically.
// Also don't clobber slots that are live for defers (see
// the code setting livedefer in epilogue).
+ if lv.noClobberArgs && n.Class == ir.PPARAM {
+ continue
+ }
clobberVar(b, n)
}
}