зеркало из https://github.com/CryptoPro/go.git
[dev.regabi] cmd/compile: convert OPANIC argument to interface{} during typecheck
Currently, typecheck leaves arguments to OPANIC as their original type. This CL changes it to insert implicit OCONVIFACE operations to convert arguments to `interface{}` like how any other function call would be handled. No immediate benefits, other than getting to remove a tiny bit of special-case logic in order.go's handling of OPANICs. Instead, the generic code path for handling OCONVIFACE is used, if necessary. Longer term, this should be marginally helpful for #43753, as it reduces the number of cases where we need values to be addressable for runtime calls. However, this does require adding some hacks to appease existing tests: 1. We need yet another kludge in inline budgeting, to ensure that reflect.flag.mustBe stays inlinable for cmd/compile/internal/test's TestIntendedInlining. 2. Since the OCONVIFACE expressions are now being introduced during typecheck, they're now visible to escape analysis. So expressions like "panic(1)" are now seen as "panic(interface{}(1))", and escape analysis warns that the "interface{}(1)" escapes to the heap. These have always escaped to heap, just now we're accurately reporting about it. (Also, unfortunately fmt.go hides implicit conversions by default in diagnostics messages, so instead of reporting "interface{}(1) escapes to heap", it actually reports "1 escapes to heap", which is confusing. However, this confusing messaging also isn't new.) Change-Id: Icedf60e1d2e464e219441b8d1233a313770272af Reviewed-on: https://go-review.googlesource.com/c/go/+/284412 Run-TryBot: Matthew Dempsky <mdempsky@google.com> TryBot-Result: Go Bot <gobot@golang.org> Reviewed-by: Cuong Manh Le <cuong.manhle.vn@gmail.com> Trust: Matthew Dempsky <mdempsky@google.com>
This commit is contained in:
Родитель
4c835f9169
Коммит
6113db0bb4
|
@ -346,6 +346,13 @@ func (v *hairyVisitor) doNode(n ir.Node) error {
|
|||
v.budget -= v.extraCallCost
|
||||
|
||||
case ir.OPANIC:
|
||||
n := n.(*ir.UnaryExpr)
|
||||
if n.X.Op() == ir.OCONVIFACE && n.X.(*ir.ConvExpr).Implicit() {
|
||||
// Hack to keep reflect.flag.mustBe inlinable for TestIntendedInlining.
|
||||
// Before CL 284412, these conversions were introduced later in the
|
||||
// compiler, so they didn't count against inlining budget.
|
||||
v.budget++
|
||||
}
|
||||
v.budget -= inlineExtraPanicCost
|
||||
|
||||
case ir.ORECOVER:
|
||||
|
|
|
@ -896,7 +896,7 @@ func tcNew(n *ir.UnaryExpr) ir.Node {
|
|||
// tcPanic typechecks an OPANIC node.
|
||||
func tcPanic(n *ir.UnaryExpr) ir.Node {
|
||||
n.X = Expr(n.X)
|
||||
n.X = DefaultLit(n.X, types.Types[types.TINTER])
|
||||
n.X = AssignConv(n.X, types.Types[types.TINTER], "argument to panic")
|
||||
if n.X.Type() == nil {
|
||||
n.SetType(nil)
|
||||
return n
|
||||
|
|
|
@ -768,14 +768,12 @@ func (o *orderState) stmt(n ir.Node) {
|
|||
orderBlock(&n.Else, o.free)
|
||||
o.out = append(o.out, n)
|
||||
|
||||
// Special: argument will be converted to interface using convT2E
|
||||
// so make sure it is an addressable temporary.
|
||||
case ir.OPANIC:
|
||||
n := n.(*ir.UnaryExpr)
|
||||
t := o.markTemp()
|
||||
n.X = o.expr(n.X, nil)
|
||||
if !n.X.Type().IsInterface() {
|
||||
n.X = o.addrTemp(n.X)
|
||||
if !n.X.Type().IsEmptyInterface() {
|
||||
base.FatalfAt(n.Pos(), "bad argument to panic: %L", n.X)
|
||||
}
|
||||
o.out = append(o.out, n)
|
||||
o.cleanTemp(t)
|
||||
|
|
|
@ -285,5 +285,5 @@ func main() {
|
|||
|
||||
//go:noinline
|
||||
func ppanic(s string) { // ERROR "leaking param: s"
|
||||
panic(s)
|
||||
panic(s) // ERROR "s escapes to heap"
|
||||
}
|
||||
|
|
|
@ -1547,7 +1547,7 @@ func foo153(v interface{}) *int { // ERROR "v does not escape"
|
|||
case int: // ERROR "moved to heap: x$"
|
||||
return &x
|
||||
}
|
||||
panic(0)
|
||||
panic(0) // ERROR "0 escapes to heap"
|
||||
}
|
||||
|
||||
// issue 8185 - &result escaping into result
|
||||
|
|
|
@ -1547,7 +1547,7 @@ func foo153(v interface{}) *int { // ERROR "v does not escape"
|
|||
case int: // ERROR "moved to heap: x$"
|
||||
return &x
|
||||
}
|
||||
panic(0)
|
||||
panic(0) // ERROR "0 escapes to heap"
|
||||
}
|
||||
|
||||
// issue 8185 - &result escaping into result
|
||||
|
|
|
@ -35,14 +35,14 @@ func f1() {
|
|||
func f2() {} // ERROR "can inline f2"
|
||||
|
||||
// No inline for recover; panic now allowed to inline.
|
||||
func f3() { panic(1) } // ERROR "can inline f3"
|
||||
func f3() { panic(1) } // ERROR "can inline f3" "1 escapes to heap"
|
||||
func f4() { recover() }
|
||||
|
||||
func f5() *byte {
|
||||
type T struct {
|
||||
x [1]byte
|
||||
}
|
||||
t := new(T) // ERROR "new.T. escapes to heap"
|
||||
t := new(T) // ERROR "new.T. escapes to heap"
|
||||
return &t.x[0]
|
||||
}
|
||||
|
||||
|
@ -52,6 +52,6 @@ func f6() *byte {
|
|||
y byte
|
||||
}
|
||||
}
|
||||
t := new(T) // ERROR "new.T. escapes to heap"
|
||||
t := new(T) // ERROR "new.T. escapes to heap"
|
||||
return &t.x.y
|
||||
}
|
||||
|
|
|
@ -60,7 +60,7 @@ func test1(iter int) {
|
|||
}
|
||||
|
||||
if len(m) != maxI {
|
||||
panic(fmt.Sprintf("iter %d: maxI = %d, len(m) = %d", iter, maxI, len(m))) // ERROR "iter escapes to heap$" "len\(m\) escapes to heap$" "maxI escapes to heap$" "... argument does not escape$"
|
||||
panic(fmt.Sprintf("iter %d: maxI = %d, len(m) = %d", iter, maxI, len(m))) // ERROR "iter escapes to heap$" "len\(m\) escapes to heap$" "maxI escapes to heap$" "... argument does not escape$" "fmt.Sprintf\(.*\) escapes to heap"
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -84,7 +84,7 @@ func test2(iter int) {
|
|||
}
|
||||
|
||||
if len(m) != maxI {
|
||||
panic(fmt.Sprintf("iter %d: maxI = %d, len(m) = %d", iter, maxI, len(m))) // ERROR "iter escapes to heap$" "len\(m\) escapes to heap$" "maxI escapes to heap$" "... argument does not escape$"
|
||||
panic(fmt.Sprintf("iter %d: maxI = %d, len(m) = %d", iter, maxI, len(m))) // ERROR "iter escapes to heap$" "len\(m\) escapes to heap$" "maxI escapes to heap$" "... argument does not escape$" "fmt.Sprintf\(.*\) escapes to heap"
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -110,7 +110,7 @@ func test3(iter int) {
|
|||
}
|
||||
|
||||
if *m != maxI {
|
||||
panic(fmt.Sprintf("iter %d: maxI = %d, *m = %d", iter, maxI, *m)) // ERROR "\*m escapes to heap$" "iter escapes to heap$" "maxI escapes to heap$" "... argument does not escape$"
|
||||
panic(fmt.Sprintf("iter %d: maxI = %d, *m = %d", iter, maxI, *m)) // ERROR "\*m escapes to heap$" "iter escapes to heap$" "maxI escapes to heap$" "... argument does not escape$" "fmt.Sprintf\(.*\) escapes to heap"
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -136,7 +136,7 @@ func test4(iter int) {
|
|||
}
|
||||
|
||||
if *m != maxI {
|
||||
panic(fmt.Sprintf("iter %d: maxI = %d, *m = %d", iter, maxI, *m)) // ERROR "\*m escapes to heap$" "iter escapes to heap$" "maxI escapes to heap$" "... argument does not escape$"
|
||||
panic(fmt.Sprintf("iter %d: maxI = %d, *m = %d", iter, maxI, *m)) // ERROR "\*m escapes to heap$" "iter escapes to heap$" "maxI escapes to heap$" "... argument does not escape$" "fmt.Sprintf\(.*\) escapes to heap"
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -167,7 +167,7 @@ func test5(iter int) {
|
|||
}
|
||||
|
||||
if *m != maxI {
|
||||
panic(fmt.Sprintf("iter %d: maxI = %d, *m = %d", iter, maxI, *m)) // ERROR "\*m escapes to heap$" "iter escapes to heap$" "maxI escapes to heap$" "... argument does not escape$"
|
||||
panic(fmt.Sprintf("iter %d: maxI = %d, *m = %d", iter, maxI, *m)) // ERROR "\*m escapes to heap$" "iter escapes to heap$" "maxI escapes to heap$" "... argument does not escape$" "fmt.Sprintf\(.*\) escapes to heap"
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -185,6 +185,6 @@ func test6(iter int) {
|
|||
}
|
||||
|
||||
if *m != maxI {
|
||||
panic(fmt.Sprintf("iter %d: maxI = %d, *m = %d", iter, maxI, *m)) // ERROR "\*m escapes to heap$" "iter escapes to heap$" "maxI escapes to heap$" "... argument does not escape$"
|
||||
panic(fmt.Sprintf("iter %d: maxI = %d, *m = %d", iter, maxI, *m)) // ERROR "\*m escapes to heap$" "iter escapes to heap$" "maxI escapes to heap$" "... argument does not escape$" "fmt.Sprintf\(.*\) escapes to heap"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -41,7 +41,7 @@ func bufferNoEscape3(xs []string) string { // ERROR "xs does not escape$"
|
|||
|
||||
func bufferNoEscape4() []byte {
|
||||
var b bytes.Buffer
|
||||
b.Grow(64) // ERROR "bufferNoEscape4 ignoring self-assignment in bytes.b.buf = bytes.b.buf\[:bytes.m\]$" "inlining call to bytes.\(\*Buffer\).Grow$"
|
||||
b.Grow(64) // ERROR "bufferNoEscape4 ignoring self-assignment in bytes.b.buf = bytes.b.buf\[:bytes.m\]$" "inlining call to bytes.\(\*Buffer\).Grow$" "string\(.*\) escapes to heap"
|
||||
useBuffer(&b)
|
||||
return b.Bytes() // ERROR "inlining call to bytes.\(\*Buffer\).Bytes$"
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче