mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
cmd/compile: ensure bloop only kept alive addressable nodes
Fixes #76636 Change-Id: I881f88dbf62a901452c1d77e6ffca651451c7790 Reviewed-on: https://go-review.googlesource.com/c/go/+/725420 Auto-Submit: Cuong Manh Le <cuong.manhle.vn@gmail.com> LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com> Reviewed-by: Junyang Shao <shaojunyang@google.com> Reviewed-by: Keith Randall <khr@golang.org> Reviewed-by: Keith Randall <khr@google.com>
This commit is contained in:
parent
7cab1b1b26
commit
509ddf3868
2 changed files with 24 additions and 5 deletions
|
|
@ -73,6 +73,14 @@ func getNameFromNode(n ir.Node) *ir.Name {
|
|||
return nil
|
||||
}
|
||||
|
||||
// getAddressableNameFromNode is like getNameFromNode but returns nil if the node is not addressable.
|
||||
func getAddressableNameFromNode(n ir.Node) *ir.Name {
|
||||
if name := getNameFromNode(n); name != nil && ir.IsAddressable(name) {
|
||||
return name
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// keepAliveAt returns a statement that is either curNode, or a
|
||||
// block containing curNode followed by a call to runtime.KeepAlive for each
|
||||
// node in ns. These calls ensure that nodes in ns will be live until
|
||||
|
|
@ -94,6 +102,9 @@ func keepAliveAt(ns []ir.Node, curNode ir.Node) ir.Node {
|
|||
if n.Sym().IsBlank() {
|
||||
continue
|
||||
}
|
||||
if !ir.IsAddressable(n) {
|
||||
base.FatalfAt(n.Pos(), "keepAliveAt: node %v is not addressable", n)
|
||||
}
|
||||
arg := ir.NewConvExpr(pos, ir.OCONV, types.Types[types.TUNSAFEPTR], typecheck.NodAddr(n))
|
||||
if !n.Type().IsInterface() {
|
||||
srcRType0 := reflectdata.TypePtrAt(pos, n.Type())
|
||||
|
|
@ -129,7 +140,7 @@ func preserveStmt(curFn *ir.Func, stmt ir.Node) (ret ir.Node) {
|
|||
switch n := stmt.(type) {
|
||||
case *ir.AssignStmt:
|
||||
// Peel down struct and slice indexing to get the names
|
||||
name := getNameFromNode(n.X)
|
||||
name := getAddressableNameFromNode(n.X)
|
||||
if name != nil {
|
||||
debugName(name, n.Pos())
|
||||
ret = keepAliveAt([]ir.Node{name}, n)
|
||||
|
|
@ -144,7 +155,7 @@ func preserveStmt(curFn *ir.Func, stmt ir.Node) (ret ir.Node) {
|
|||
case *ir.AssignListStmt:
|
||||
ns := []ir.Node{}
|
||||
for _, lhs := range n.Lhs {
|
||||
name := getNameFromNode(lhs)
|
||||
name := getAddressableNameFromNode(lhs)
|
||||
if name != nil {
|
||||
debugName(name, n.Pos())
|
||||
ns = append(ns, name)
|
||||
|
|
@ -159,7 +170,7 @@ func preserveStmt(curFn *ir.Func, stmt ir.Node) (ret ir.Node) {
|
|||
}
|
||||
ret = keepAliveAt(ns, n)
|
||||
case *ir.AssignOpStmt:
|
||||
name := getNameFromNode(n.X)
|
||||
name := getAddressableNameFromNode(n.X)
|
||||
if name != nil {
|
||||
debugName(name, n.Pos())
|
||||
ret = keepAliveAt([]ir.Node{name}, n)
|
||||
|
|
@ -206,7 +217,7 @@ func preserveStmt(curFn *ir.Func, stmt ir.Node) (ret ir.Node) {
|
|||
argTmps := []ir.Node{}
|
||||
names := []ir.Node{}
|
||||
for i, a := range n.Args {
|
||||
if name := getNameFromNode(a); name != nil {
|
||||
if name := getAddressableNameFromNode(a); name != nil {
|
||||
// If they are name, keep them alive directly.
|
||||
debugName(name, n.Pos())
|
||||
names = append(names, name)
|
||||
|
|
@ -215,7 +226,7 @@ func preserveStmt(curFn *ir.Func, stmt ir.Node) (ret ir.Node) {
|
|||
s := a.(*ir.CompLitExpr)
|
||||
ns := []ir.Node{}
|
||||
for i, elem := range s.List {
|
||||
if name := getNameFromNode(elem); name != nil {
|
||||
if name := getAddressableNameFromNode(elem); name != nil {
|
||||
debugName(name, n.Pos())
|
||||
ns = append(ns, name)
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -25,6 +25,12 @@ func caninlineVariadic(x ...int) { // ERROR "can inline caninlineVariadic" "x do
|
|||
something = x[0]
|
||||
}
|
||||
|
||||
func receiver(f func()) { // ERROR "can inline receiver" "f does not escape"
|
||||
f()
|
||||
}
|
||||
|
||||
func argument() {} // ERROR "can inline argument"
|
||||
|
||||
func test(b *testing.B, localsink, cond int) { // ERROR ".*"
|
||||
for i := 0; i < b.N; i++ {
|
||||
caninline(1) // ERROR "inlining call to caninline"
|
||||
|
|
@ -49,5 +55,7 @@ func test(b *testing.B, localsink, cond int) { // ERROR ".*"
|
|||
{
|
||||
caninline(1) // ERROR "inlining call to caninline" "function result will be kept alive"
|
||||
}
|
||||
|
||||
receiver(argument) // ERROR inlining call to receiver" "function arg will be kept alive"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue