mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
cmd/compile: improve coverage of nowritebarrierrec check
The current go:nowritebarrierrec checker has two problems that limit its coverage: 1. It doesn't understand that systemstack calls its argument, which means there are several cases where we fail to detect prohibited write barriers. 2. It only observes calls in the AST, so calls constructed during lowering by SSA aren't followed. This CL completely rewrites this checker to address these issues. The current checker runs entirely after walk and uses visitBottomUp, which introduces several problems for checking across systemstack. First, visitBottomUp itself doesn't understand systemstack calls, so the callee may be ordered after the caller, causing the checker to fail to propagate constraints. Second, many systemstack calls are passed a closure, which is quite difficult to resolve back to the function definition after transformclosure and walk have run. Third, visitBottomUp works exclusively on the AST, so it can't observe calls created by SSA. To address these problems, this commit splits the check into two phases and rewrites it to use a call graph generated during SSA lowering. The first phase runs before transformclosure/walk and simply records systemstack arguments when they're easy to get. Then, it modifies genssa to record static call edges at the point where we're lowering to Progs (which is the latest point at which position information is conveniently available). Finally, the second phase runs after all functions have been lowered and uses a direct BFS walk of the call graph (combining systemstack calls with static calls) to find prohibited write barriers and construct nice error messages. Fixes #22384. For #22460. Change-Id: I39668f7f2366ab3c1ab1a71eaf25484d25349540 Reviewed-on: https://go-review.googlesource.com/72773 Run-TryBot: Austin Clements <austin@google.com> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Matthew Dempsky <mdempsky@google.com>
This commit is contained in:
parent
3526d8031a
commit
5a4b6bce37
6 changed files with 244 additions and 105 deletions
|
|
@ -130,6 +130,8 @@ func supportsDynlink(arch *sys.Arch) bool {
|
|||
var timings Timings
|
||||
var benchfile string
|
||||
|
||||
var nowritebarrierrecCheck *nowritebarrierrecChecker
|
||||
|
||||
// Main parses flags and Go source files specified in the command-line
|
||||
// arguments, type-checks the parsed Go package, compiles functions to machine
|
||||
// code, and finally writes the compiled package definition to disk.
|
||||
|
|
@ -568,6 +570,14 @@ func Main(archInit func(*Arch)) {
|
|||
escapes(xtop)
|
||||
|
||||
if dolinkobj {
|
||||
// Collect information for go:nowritebarrierrec
|
||||
// checking. This must happen before transformclosure.
|
||||
// We'll do the final check after write barriers are
|
||||
// inserted.
|
||||
if compiling_runtime {
|
||||
nowritebarrierrecCheck = newNowritebarrierrecChecker()
|
||||
}
|
||||
|
||||
// Phase 7: Transform closure bodies to properly reference captured variables.
|
||||
// This needs to happen before walk, because closures must be transformed
|
||||
// before walk reaches a call of a closure.
|
||||
|
|
@ -616,8 +626,11 @@ func Main(archInit func(*Arch)) {
|
|||
// at least until this convoluted structure has been unwound.
|
||||
nBackendWorkers = 1
|
||||
|
||||
if compiling_runtime {
|
||||
checknowritebarrierrec()
|
||||
if nowritebarrierrecCheck != nil {
|
||||
// Write barriers are now known. Check the
|
||||
// call graph.
|
||||
nowritebarrierrecCheck.check()
|
||||
nowritebarrierrecCheck = nil
|
||||
}
|
||||
|
||||
// Check whether any of the functions we have compiled have gigantic stack frames.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue