summaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
authorRuss Cox <rsc@golang.org>2014-04-03 20:33:25 -0400
committerRuss Cox <rsc@golang.org>2014-04-03 20:33:25 -0400
commit75028df9fd66c2c9faff60279eceebafff28a30a (patch)
tree5a02c1492789acfff7bd1ec903060c4e995f23dd /test
parentcaa7d4e687451482359374f221104b43f0c17732 (diff)
downloadgo-75028df9fd66c2c9faff60279eceebafff28a30a.tar.gz
cmd/gc, runtime: make GODEBUG=gcdead=1 mode work with liveness
Trying to make GODEBUG=gcdead=1 work with liveness and in particular ambiguously live variables. 1. In the liveness computation, mark all ambiguously live variables as live for the entire function, except the entry. They are zeroed directly after entry, and we need them not to be poisoned thereafter. 2. In the liveness computation, compute liveness (and deadness) for all parameters, not just pointer-containing parameters. Otherwise gcdead poisons untracked scalar parameters and results. 3. Fix liveness debugging print for -live=2 to use correct bitmaps. (Was not updated for compaction during compaction CL.) 4. Correct varkill during map literal initialization. Was killing the map itself instead of the inserted value temp. 5. Disable aggressive varkill cleanup for call arguments if the call appears in a defer or go statement. 6. In the garbage collector, avoid bug scanning empty strings. An empty string is two zeros. The multiword code only looked at the first zero and then interpreted the next two bits in the bitmap as an ordinary word bitmap. For a string the bits are 11 00, so if a live string was zero length with a 0 base pointer, the poisoning code treated the length as an ordinary word with code 00, meaning it needed poisoning, turning the string into a poison-length string with base pointer 0. By the same logic I believe that a live nil slice (bits 11 01 00) will have its cap poisoned. Always scan full multiword struct. 7. In the runtime, treat both poison words (PoisonGC and PoisonStack) as invalid pointers that warrant crashes. Manual testing as follows: - Create a script called gcdead on your PATH containing: #!/bin/bash GODEBUG=gcdead=1 GOGC=10 GOTRACEBACK=2 exec "$@" - Now you can build a test and then run 'gcdead ./foo.test'. - More importantly, you can run 'go test -short -exec gcdead std' to run all the tests. Fixes issue 7676. While here, enable the precise scanning of slices, since that was disabled due to bugs like these. That now works, both with and without gcdead. Fixes issue 7549. LGTM=khr R=khr CC=golang-codereviews https://codereview.appspot.com/83410044
Diffstat (limited to 'test')
-rw-r--r--test/live.go39
1 files changed, 33 insertions, 6 deletions
diff --git a/test/live.go b/test/live.go
index 43b3c3e4c..21d3e6a5f 100644
--- a/test/live.go
+++ b/test/live.go
@@ -23,20 +23,24 @@ func f2(b bool) {
}
func f3(b bool) {
- print(0)
+ // Because x and y are ambiguously live, they appear
+ // live throughout the function, to avoid being poisoned
+ // in GODEBUG=gcdead=1 mode.
+
+ print(0) // ERROR "live at call to printint: x y$"
if b == false {
- print(0) // nothing live here
+ print(0) // ERROR "live at call to printint: x y$"
return
}
if b {
var x *int
- print(&x) // ERROR "live at call to printpointer: x$"
- print(&x) // ERROR "live at call to printpointer: x$"
+ print(&x) // ERROR "live at call to printpointer: x y$"
+ print(&x) // ERROR "live at call to printpointer: x y$"
} else {
var y *int
- print(&y) // ERROR "live at call to printpointer: y$"
- print(&y) // ERROR "live at call to printpointer: y$"
+ print(&y) // ERROR "live at call to printpointer: x y$"
+ print(&y) // ERROR "live at call to printpointer: x y$"
}
print(0) // ERROR "live at call to printint: x y$" "x \(type \*int\) is ambiguously live" "y \(type \*int\) is ambiguously live"
}
@@ -371,6 +375,29 @@ func f27(b bool) {
}
call27(func() {x++}) // ERROR "live at call to call27: autotmp_[0-9]+$"
call27(func() {x++}) // ERROR "live at call to call27: autotmp_[0-9]+$"
+ println()
+}
+
+// but defer does escape to later execution in the function
+
+func f27defer(b bool) {
+ x := 0
+ if b {
+ defer call27(func() {x++}) // ERROR "live at call to deferproc: autotmp_[0-9]+$" "live at call to deferreturn: autotmp_[0-9]+$"
+ }
+ defer call27(func() {x++}) // ERROR "live at call to deferproc: autotmp_[0-9]+ autotmp_[0-9]+$" "live at call to deferreturn: autotmp_[0-9]+ autotmp_[0-9]+$" "ambiguously live"
+ println() // ERROR "live at call to printnl: autotmp_[0-9]+ autotmp_[0-9]+$"
+} // ERROR "live at call to deferreturn: autotmp_[0-9]+ autotmp_[0-9]+$"
+
+// and newproc (go) escapes to the heap
+
+func f27go(b bool) {
+ x := 0
+ if b {
+ go call27(func() {x++}) // ERROR "live at call to new: &x" "live at call to newproc: &x$"
+ }
+ go call27(func() {x++}) // ERROR "live at call to new: &x"
+ println()
}
//go:noescape