summaryrefslogtreecommitdiff
path: root/test/nilptr3.go
diff options
context:
space:
mode:
authorRuss Cox <rsc@golang.org>2014-05-15 15:34:53 -0400
committerRuss Cox <rsc@golang.org>2014-05-15 15:34:53 -0400
commit17e56eaa9da22104930c0185ae5b7daa562bb17d (patch)
tree31a8c2d31468c80f3c2ba4086c1205707c56c2a1 /test/nilptr3.go
parent191b16d00c36c11defbe0f901bc934d2cd642e0b (diff)
downloadgo-17e56eaa9da22104930c0185ae5b7daa562bb17d.tar.gz
cmd/gc: correct handling of globals, func args, results
Globals, function arguments, and results are special cases in registerization. Globals must be flushed aggressively, because nearly any operation can cause a panic, and the recovery code must see the latest values. Globals also must be loaded aggressively, because nearly any store through a pointer might be updating a global: the compiler cannot see all the "address of" operations on globals, especially exported globals. To accomplish this, mark all globals as having their address taken, which effectively disables registerization. If a function contains a defer statement, the function results must be flushed aggressively, because nearly any operation can cause a panic, and the deferred code may call recover, causing the original function to return the current values of its function results. To accomplish this, mark all function results as having their address taken if the function contains any defer statements. This causes not just aggressive flushing but also aggressive loading. The aggressive loading is overkill but the best we can do in the current code. Function arguments must be considered live at all safe points in a function, because garbage collection always preserves them: they must be up-to-date in order to be preserved correctly. Accomplish this by marking them live at all call sites. An earlier attempt at this marked function arguments as having their address taken, which disabled registerization completely, making programs slower. This CL's solution allows registerization while preserving safety. The benchmark speedup is caused by being able to registerize again (the earlier CL lost the same amount). benchmark old ns/op new ns/op delta BenchmarkEqualPort32 61.4 56.0 -8.79% benchmark old MB/s new MB/s speedup BenchmarkEqualPort32 521.56 570.97 1.09x Fixes issue 1304. (again) Fixes issue 7944. (again) Fixes issue 7984. Fixes issue 7995. LGTM=khr R=golang-codereviews, khr CC=golang-codereviews, iant, r https://codereview.appspot.com/97500044
Diffstat (limited to 'test/nilptr3.go')
-rw-r--r--test/nilptr3.go102
1 files changed, 51 insertions, 51 deletions
diff --git a/test/nilptr3.go b/test/nilptr3.go
index 08597a02d..2757daef0 100644
--- a/test/nilptr3.go
+++ b/test/nilptr3.go
@@ -17,7 +17,7 @@ type Struct struct {
type BigStruct struct {
X int
Y float64
- A [1<<20]int
+ A [1 << 20]int
Z string
}
@@ -29,93 +29,94 @@ type Empty1 struct {
}
var (
- intp *int
- arrayp *[10]int
- array0p *[0]int
- bigarrayp *[1<<26]int
- structp *Struct
+ intp *int
+ arrayp *[10]int
+ array0p *[0]int
+ bigarrayp *[1 << 26]int
+ structp *Struct
bigstructp *BigStruct
- emptyp *Empty
- empty1p *Empty1
+ emptyp *Empty
+ empty1p *Empty1
)
func f1() {
_ = *intp // ERROR "generated nil check"
-
+
// This one should be removed but the block copy needs
// to be turned into its own pseudo-op in order to see
// the indirect.
_ = *arrayp // ERROR "generated nil check"
-
- // 0-byte indirect doesn't suffice
+
+ // 0-byte indirect doesn't suffice.
+ // we don't registerize globals, so there are no removed repeated nil checks.
+ _ = *array0p // ERROR "generated nil check"
_ = *array0p // ERROR "generated nil check"
- _ = *array0p // ERROR "removed repeated nil check" 386
- _ = *intp // ERROR "removed repeated nil check"
- _ = *arrayp // ERROR "removed repeated nil check"
+ _ = *intp // ERROR "generated nil check"
+ _ = *arrayp // ERROR "generated nil check"
_ = *structp // ERROR "generated nil check"
- _ = *emptyp // ERROR "generated nil check"
- _ = *arrayp // ERROR "removed repeated nil check"
+ _ = *emptyp // ERROR "generated nil check"
+ _ = *arrayp // ERROR "generated nil check"
}
func f2() {
var (
- intp *int
- arrayp *[10]int
- array0p *[0]int
- bigarrayp *[1<<20]int
- structp *Struct
+ intp *int
+ arrayp *[10]int
+ array0p *[0]int
+ bigarrayp *[1 << 20]int
+ structp *Struct
bigstructp *BigStruct
- emptyp *Empty
- empty1p *Empty1
+ emptyp *Empty
+ empty1p *Empty1
)
- _ = *intp // ERROR "generated nil check"
- _ = *arrayp // ERROR "generated nil check"
- _ = *array0p // ERROR "generated nil check"
- _ = *array0p // ERROR "removed repeated nil check"
- _ = *intp // ERROR "removed repeated nil check"
- _ = *arrayp // ERROR "removed repeated nil check"
- _ = *structp // ERROR "generated nil check"
- _ = *emptyp // ERROR "generated nil check"
- _ = *arrayp // ERROR "removed repeated nil check"
- _ = *bigarrayp // ERROR "generated nil check" ARM removed nil check before indirect!!
+ _ = *intp // ERROR "generated nil check"
+ _ = *arrayp // ERROR "generated nil check"
+ _ = *array0p // ERROR "generated nil check"
+ _ = *array0p // ERROR "removed repeated nil check"
+ _ = *intp // ERROR "removed repeated nil check"
+ _ = *arrayp // ERROR "removed repeated nil check"
+ _ = *structp // ERROR "generated nil check"
+ _ = *emptyp // ERROR "generated nil check"
+ _ = *arrayp // ERROR "removed repeated nil check"
+ _ = *bigarrayp // ERROR "generated nil check" ARM removed nil check before indirect!!
_ = *bigstructp // ERROR "generated nil check"
- _ = *empty1p // ERROR "generated nil check"
+ _ = *empty1p // ERROR "generated nil check"
}
func fx10k() *[10000]int
-var b bool
+var b bool
func f3(x *[10000]int) {
// Using a huge type and huge offsets so the compiler
// does not expect the memory hardware to fault.
_ = x[9999] // ERROR "generated nil check"
-
+
for {
if x[9999] != 0 { // ERROR "generated nil check"
break
}
}
-
- x = fx10k()
+
+ x = fx10k()
_ = x[9999] // ERROR "generated nil check"
if b {
_ = x[9999] // ERROR "removed repeated nil check"
} else {
_ = x[9999] // ERROR "removed repeated nil check"
- }
+ }
_ = x[9999] // ERROR "generated nil check"
- x = fx10k()
+ x = fx10k()
if b {
_ = x[9999] // ERROR "generated nil check"
} else {
_ = x[9999] // ERROR "generated nil check"
- }
+ }
_ = x[9999] // ERROR "generated nil check"
-
+
fx10k()
// This one is a bit redundant, if we figured out that
// x wasn't going to change across the function call.
@@ -145,7 +146,7 @@ func f3b() {
_ = &x[9] // ERROR "removed repeated nil check"
}
-func fx10() *[10]int
+func fx10() *[10]int
func f4(x *[10]int) {
// Most of these have no checks because a real memory reference follows,
@@ -153,14 +154,14 @@ func f4(x *[10]int) {
// in the first unmapped page of memory.
_ = x[9] // ERROR "removed nil check before indirect"
-
+
for {
if x[9] != 0 { // ERROR "removed nil check before indirect"
break
}
}
-
- x = fx10()
+
+ x = fx10()
_ = x[9] // ERROR "removed nil check before indirect"
if b {
_ = x[9] // ERROR "removed nil check before indirect"
@@ -169,17 +170,17 @@ func f4(x *[10]int) {
}
_ = x[9] // ERROR "removed nil check before indirect"
- x = fx10()
+ x = fx10()
if b {
_ = x[9] // ERROR "removed nil check before indirect"
} else {
_ = &x[9] // ERROR "generated nil check"
- }
+ }
_ = x[9] // ERROR "removed nil check before indirect"
-
+
fx10()
_ = x[9] // ERROR "removed nil check before indirect"
-
+
x = fx10()
y := fx10()
_ = &x[9] // ERROR "generated nil check"
@@ -188,4 +189,3 @@ func f4(x *[10]int) {
x = y
_ = &x[9] // ERROR "removed repeated nil check"
}
-