diff options
| author | Michael Pratt <mpratt@google.com> | 2023-11-16 14:58:37 -0500 |
|---|---|---|
| committer | Michael Pratt <mpratt@google.com> | 2023-11-16 21:31:06 +0000 |
| commit | 3fd5c357a3a763f70f3ed684caed878e732e6ebe (patch) | |
| tree | b9d9367b6bf0473407b4416affcd47f74cd43fcb /src/cmd | |
| parent | e62bf150cc0802b3697da315ee41e19c0bbfb7eb (diff) | |
| download | go-3fd5c357a3a763f70f3ed684caed878e732e6ebe.tar.xz | |
cmd/compile: don't devirtualize calls to runtime.memhash_varlen
runtime.memhash_varlen is defined as a normal function, but it is
actually a closure. All references are generated by
cmd/compile/internal/reflectdata.genhash, which creates a closure
containing the size of the type, which memhash_varlen accesses with
runtime.getclosureptr.
Since this doesn't look like a normal closure, ir.Func.OClosure is not
set, thus PGO function value devirtualization is willing to devirtualize
it, generating a call that completely ignores the closure context. This
causes memhash_varlen to either crash or generate incorrect results.
Skip this function, which is the only caller of getclosureptr.
Unfortunately there isn't a good way to detect these ineligible
functions more generally.
Fixes #64209.
Change-Id: Ibf509406667c6d4e5d431f10e5b1d1f926ecd7dc
Reviewed-on: https://go-review.googlesource.com/c/go/+/543195
Reviewed-by: Cherry Mui <cherryyz@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Diffstat (limited to 'src/cmd')
| -rw-r--r-- | src/cmd/compile/internal/devirtualize/pgo.go | 9 |
1 files changed, 9 insertions, 0 deletions
diff --git a/src/cmd/compile/internal/devirtualize/pgo.go b/src/cmd/compile/internal/devirtualize/pgo.go index 0a34e7eb8d..7b6c8ba0c0 100644 --- a/src/cmd/compile/internal/devirtualize/pgo.go +++ b/src/cmd/compile/internal/devirtualize/pgo.go @@ -241,6 +241,15 @@ func maybeDevirtualizeFunctionCall(p *pgo.Profile, fn *ir.Func, call *ir.CallExp } return nil, nil, 0 } + // runtime.memhash_varlen does not look like a closure, but it uses + // runtime.getclosureptr to access data encoded by callers, which are + // are generated by cmd/compile/internal/reflectdata.genhash. + if callee.Sym().Pkg.Path == "runtime" && callee.Sym().Name == "memhash_varlen" { + if base.Debug.PGODebug >= 3 { + fmt.Printf("callee %s is a closure (runtime.memhash_varlen), skipping\n", ir.FuncName(callee)) + } + return nil, nil, 0 + } // TODO(prattmic): We don't properly handle methods as callees in two // different dimensions: // |
