mirror of
https://github.com/golang/go
synced 2024-11-24 08:40:14 -07:00
b700cb4974
The new channel and map runtime routines take pointers to values, typically temporaries. Without help, the compiler cannot tell when those temporaries stop being needed, because it isn't sure what happened to the pointer. Arrange to insert explicit VARKILL instructions for these temporaries so that the liveness analysis can avoid seeing them as "ambiguously live". The change is made in order.c, which was already in charge of introducing temporaries to preserve the order-of-evaluation guarantees. Now its job has expanded to include introducing temporaries as needed by runtime routines, and then also inserting the VARKILL annotations for all these temporaries, so that their lifetimes can be shortened. In order to do its job for the map runtime routines, order.c arranges that all map lookups or map assignments have the form: x = m[k] x, y = m[k] m[k] = x where x, y, and k are simple variables (often temporaries). Likewise, receiving from a channel is now always: x = <-c In order to provide the map guarantee, order.c is responsible for rewriting x op= y into x = x op y, so that m[k] += z becomes t = m[k] t2 = t + z m[k] = t2 While here, fix a few bugs in order.c's traversal: it was failing to walk into select and switch case bodies, so order of evaluation guarantees were not preserved in those situations. Added tests to test/reorder2.go. Fixes #7671. In gc/popt's temporary-merging optimization, allow merging of temporaries with their address taken as long as the liveness ranges do not intersect. (There is a good chance of that now that we have VARKILL annotations to limit the liveness range.) Explicitly killing temporaries cuts the number of ambiguously live temporaries that must be zeroed in the godoc binary from 860 to 711, or -17%. There is more work to be done, but this is a good checkpoint. Update #7345 LGTM=khr R=khr CC=golang-codereviews https://golang.org/cl/81940043
344 lines
7.3 KiB
Go
344 lines
7.3 KiB
Go
// run
|
|
|
|
// Copyright 2010 The Go Authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style
|
|
// license that can be found in the LICENSE file.
|
|
|
|
// Test reorderings; derived from fixedbugs/bug294.go.
|
|
|
|
package main
|
|
|
|
var log string
|
|
|
|
type TT int
|
|
|
|
func (t TT) a(s string) TT {
|
|
log += "a(" + s + ")"
|
|
return t
|
|
}
|
|
|
|
func (TT) b(s string) string {
|
|
log += "b(" + s + ")"
|
|
return s
|
|
}
|
|
|
|
type F func(s string) F
|
|
|
|
func a(s string) F {
|
|
log += "a(" + s + ")"
|
|
return F(a)
|
|
}
|
|
|
|
func b(s string) string {
|
|
log += "b(" + s + ")"
|
|
return s
|
|
}
|
|
|
|
type I interface {
|
|
a(s string) I
|
|
b(s string) string
|
|
}
|
|
|
|
type T1 int
|
|
|
|
func (t T1) a(s string) I {
|
|
log += "a(" + s + ")"
|
|
return t
|
|
}
|
|
|
|
func (T1) b(s string) string {
|
|
log += "b(" + s + ")"
|
|
return s
|
|
}
|
|
|
|
// f(g(), h()) where g is not inlinable but h is will have the same problem.
|
|
// As will x := g() + h() (same conditions).
|
|
// And g() <- h().
|
|
func f(x, y string) {
|
|
log += "f(" + x + ", " + y + ")"
|
|
}
|
|
|
|
func ff(x, y string) {
|
|
for false {
|
|
} // prevent inl
|
|
log += "ff(" + x + ", " + y + ")"
|
|
}
|
|
|
|
func h(x string) string {
|
|
log += "h(" + x + ")"
|
|
return x
|
|
}
|
|
|
|
func g(x string) string {
|
|
for false {
|
|
} // prevent inl
|
|
log += "g(" + x + ")"
|
|
return x
|
|
}
|
|
|
|
func main() {
|
|
err := 0
|
|
var t TT
|
|
if a("1")("2")("3"); log != "a(1)a(2)a(3)" {
|
|
println("expecting a(1)a(2)a(3) , got ", log)
|
|
err++
|
|
}
|
|
log = ""
|
|
|
|
if t.a("1").a(t.b("2")); log != "a(1)b(2)a(2)" {
|
|
println("expecting a(1)b(2)a(2), got ", log)
|
|
err++
|
|
}
|
|
log = ""
|
|
if a("3")(b("4"))(b("5")); log != "a(3)b(4)a(4)b(5)a(5)" {
|
|
println("expecting a(3)b(4)a(4)b(5)a(5), got ", log)
|
|
err++
|
|
}
|
|
log = ""
|
|
var i I = T1(0)
|
|
if i.a("6").a(i.b("7")).a(i.b("8")).a(i.b("9")); log != "a(6)b(7)a(7)b(8)a(8)b(9)a(9)" {
|
|
println("expecting a(6)ba(7)ba(8)ba(9), got", log)
|
|
err++
|
|
}
|
|
log = ""
|
|
|
|
if s := t.a("1").b("3"); log != "a(1)b(3)" || s != "3" {
|
|
println("expecting a(1)b(3) and 3, got ", log, " and ", s)
|
|
err++
|
|
}
|
|
log = ""
|
|
|
|
if s := t.a("1").a(t.b("2")).b("3") + t.a("4").b("5"); log != "a(1)b(2)a(2)b(3)a(4)b(5)" || s != "35" {
|
|
println("expecting a(1)b(2)a(2)b(3)a(4)b(5) and 35, got ", log, " and ", s)
|
|
err++
|
|
}
|
|
log = ""
|
|
|
|
if s := t.a("4").b("5") + t.a("1").a(t.b("2")).b("3"); log != "a(4)b(5)a(1)b(2)a(2)b(3)" || s != "53" {
|
|
println("expecting a(4)b(5)a(1)b(2)a(2)b(3) and 35, got ", log, " and ", s)
|
|
err++
|
|
}
|
|
log = ""
|
|
|
|
if ff(g("1"), g("2")); log != "g(1)g(2)ff(1, 2)" {
|
|
println("expecting g(1)g(2)ff..., got ", log)
|
|
err++
|
|
}
|
|
log = ""
|
|
|
|
if ff(g("1"), h("2")); log != "g(1)h(2)ff(1, 2)" {
|
|
println("expecting g(1)h(2)ff..., got ", log)
|
|
err++
|
|
}
|
|
log = ""
|
|
|
|
if ff(h("1"), g("2")); log != "h(1)g(2)ff(1, 2)" {
|
|
println("expecting h(1)g(2)ff..., got ", log)
|
|
err++
|
|
}
|
|
log = ""
|
|
|
|
if ff(h("1"), h("2")); log != "h(1)h(2)ff(1, 2)" {
|
|
println("expecting h(1)h(2)ff..., got ", log)
|
|
err++
|
|
}
|
|
log = ""
|
|
|
|
if s := g("1") + g("2"); log != "g(1)g(2)" || s != "12" {
|
|
println("expecting g1g2 and 12, got ", log, " and ", s)
|
|
err++
|
|
}
|
|
log = ""
|
|
|
|
if s := g("1") + h("2"); log != "g(1)h(2)" || s != "12" {
|
|
println("expecting g1h2 and 12, got ", log, " and ", s)
|
|
err++
|
|
}
|
|
log = ""
|
|
|
|
if s := h("1") + g("2"); log != "h(1)g(2)" || s != "12" {
|
|
println("expecting h1g2 and 12, got ", log, " and ", s)
|
|
err++
|
|
}
|
|
log = ""
|
|
|
|
if s := h("1") + h("2"); log != "h(1)h(2)" || s != "12" {
|
|
println("expecting h1h2 and 12, got ", log, " and ", s)
|
|
err++
|
|
}
|
|
log = ""
|
|
|
|
x := 0
|
|
switch x {
|
|
case 0:
|
|
if a("1")("2")("3"); log != "a(1)a(2)a(3)" {
|
|
println("in switch, expecting a(1)a(2)a(3) , got ", log)
|
|
err++
|
|
}
|
|
log = ""
|
|
|
|
if t.a("1").a(t.b("2")); log != "a(1)b(2)a(2)" {
|
|
println("in switch, expecting a(1)b(2)a(2), got ", log)
|
|
err++
|
|
}
|
|
log = ""
|
|
if a("3")(b("4"))(b("5")); log != "a(3)b(4)a(4)b(5)a(5)" {
|
|
println("in switch, expecting a(3)b(4)a(4)b(5)a(5), got ", log)
|
|
err++
|
|
}
|
|
log = ""
|
|
var i I = T1(0)
|
|
if i.a("6").a(i.b("7")).a(i.b("8")).a(i.b("9")); log != "a(6)b(7)a(7)b(8)a(8)b(9)a(9)" {
|
|
println("in switch, expecting a(6)ba(7)ba(8)ba(9), got", log)
|
|
err++
|
|
}
|
|
log = ""
|
|
}
|
|
|
|
c := make(chan int, 1)
|
|
c <- 1
|
|
select {
|
|
case c <- 0:
|
|
case c <- 1:
|
|
case <-c:
|
|
if a("1")("2")("3"); log != "a(1)a(2)a(3)" {
|
|
println("in select1, expecting a(1)a(2)a(3) , got ", log)
|
|
err++
|
|
}
|
|
log = ""
|
|
|
|
if t.a("1").a(t.b("2")); log != "a(1)b(2)a(2)" {
|
|
println("in select1, expecting a(1)b(2)a(2), got ", log)
|
|
err++
|
|
}
|
|
log = ""
|
|
if a("3")(b("4"))(b("5")); log != "a(3)b(4)a(4)b(5)a(5)" {
|
|
println("in select1, expecting a(3)b(4)a(4)b(5)a(5), got ", log)
|
|
err++
|
|
}
|
|
log = ""
|
|
var i I = T1(0)
|
|
if i.a("6").a(i.b("7")).a(i.b("8")).a(i.b("9")); log != "a(6)b(7)a(7)b(8)a(8)b(9)a(9)" {
|
|
println("in select1, expecting a(6)ba(7)ba(8)ba(9), got", log)
|
|
err++
|
|
}
|
|
log = ""
|
|
}
|
|
|
|
c <- 1
|
|
select {
|
|
case <-c:
|
|
if a("1")("2")("3"); log != "a(1)a(2)a(3)" {
|
|
println("in select2, expecting a(1)a(2)a(3) , got ", log)
|
|
err++
|
|
}
|
|
log = ""
|
|
|
|
if t.a("1").a(t.b("2")); log != "a(1)b(2)a(2)" {
|
|
println("in select2, expecting a(1)b(2)a(2), got ", log)
|
|
err++
|
|
}
|
|
log = ""
|
|
if a("3")(b("4"))(b("5")); log != "a(3)b(4)a(4)b(5)a(5)" {
|
|
println("in select2, expecting a(3)b(4)a(4)b(5)a(5), got ", log)
|
|
err++
|
|
}
|
|
log = ""
|
|
var i I = T1(0)
|
|
if i.a("6").a(i.b("7")).a(i.b("8")).a(i.b("9")); log != "a(6)b(7)a(7)b(8)a(8)b(9)a(9)" {
|
|
println("in select2, expecting a(6)ba(7)ba(8)ba(9), got", log)
|
|
err++
|
|
}
|
|
log = ""
|
|
}
|
|
|
|
c <- 1
|
|
select {
|
|
default:
|
|
case c<-1:
|
|
case <-c:
|
|
if a("1")("2")("3"); log != "a(1)a(2)a(3)" {
|
|
println("in select3, expecting a(1)a(2)a(3) , got ", log)
|
|
err++
|
|
}
|
|
log = ""
|
|
|
|
if t.a("1").a(t.b("2")); log != "a(1)b(2)a(2)" {
|
|
println("in select3, expecting a(1)b(2)a(2), got ", log)
|
|
err++
|
|
}
|
|
log = ""
|
|
if a("3")(b("4"))(b("5")); log != "a(3)b(4)a(4)b(5)a(5)" {
|
|
println("in select3, expecting a(3)b(4)a(4)b(5)a(5), got ", log)
|
|
err++
|
|
}
|
|
log = ""
|
|
var i I = T1(0)
|
|
if i.a("6").a(i.b("7")).a(i.b("8")).a(i.b("9")); log != "a(6)b(7)a(7)b(8)a(8)b(9)a(9)" {
|
|
println("in select3, expecting a(6)ba(7)ba(8)ba(9), got", log)
|
|
err++
|
|
}
|
|
log = ""
|
|
}
|
|
|
|
c <- 1
|
|
select {
|
|
default:
|
|
case <-c:
|
|
if a("1")("2")("3"); log != "a(1)a(2)a(3)" {
|
|
println("in select4, expecting a(1)a(2)a(3) , got ", log)
|
|
err++
|
|
}
|
|
log = ""
|
|
|
|
if t.a("1").a(t.b("2")); log != "a(1)b(2)a(2)" {
|
|
println("in select4, expecting a(1)b(2)a(2), got ", log)
|
|
err++
|
|
}
|
|
log = ""
|
|
if a("3")(b("4"))(b("5")); log != "a(3)b(4)a(4)b(5)a(5)" {
|
|
println("in select4, expecting a(3)b(4)a(4)b(5)a(5), got ", log)
|
|
err++
|
|
}
|
|
log = ""
|
|
var i I = T1(0)
|
|
if i.a("6").a(i.b("7")).a(i.b("8")).a(i.b("9")); log != "a(6)b(7)a(7)b(8)a(8)b(9)a(9)" {
|
|
println("in select4, expecting a(6)ba(7)ba(8)ba(9), got", log)
|
|
err++
|
|
}
|
|
log = ""
|
|
}
|
|
|
|
select {
|
|
case <-c:
|
|
case <-c:
|
|
default:
|
|
if a("1")("2")("3"); log != "a(1)a(2)a(3)" {
|
|
println("in select5, expecting a(1)a(2)a(3) , got ", log)
|
|
err++
|
|
}
|
|
log = ""
|
|
|
|
if t.a("1").a(t.b("2")); log != "a(1)b(2)a(2)" {
|
|
println("in select5, expecting a(1)b(2)a(2), got ", log)
|
|
err++
|
|
}
|
|
log = ""
|
|
if a("3")(b("4"))(b("5")); log != "a(3)b(4)a(4)b(5)a(5)" {
|
|
println("in select5, expecting a(3)b(4)a(4)b(5)a(5), got ", log)
|
|
err++
|
|
}
|
|
log = ""
|
|
var i I = T1(0)
|
|
if i.a("6").a(i.b("7")).a(i.b("8")).a(i.b("9")); log != "a(6)b(7)a(7)b(8)a(8)b(9)a(9)" {
|
|
println("in select5, expecting a(6)ba(7)ba(8)ba(9), got", log)
|
|
err++
|
|
}
|
|
log = ""
|
|
}
|
|
|
|
if err > 0 {
|
|
panic("fail")
|
|
}
|
|
}
|